SAM3X8E (Arduino Due) Pin IO registra


9

¿Cómo funcionan los registros IO de Arduino Due? En Arduino Uno acaba de establecer DDRx, a continuación, PINxleer, PORTxescribir, me gustaría hacer lo mismo con un Arduino Due, pero tiene muchos más registros, tales como PIO_OWER, PIO_OSER, PIO_CODR, PIO_SODR, etc puedo encontrar ninguna correspondencia entre Arduino Uno y Arduino Debido registros.

También hay algunas funciones útiles, tales como pio_clear, pio_set, pio_get, y otros, todos explican aquí:

http://asf.atmel.com/docs/3.19.0/sam3x/html/group__sam__drivers__pio__group.html

Ahora, creo que he entendido lo que hacen las tres funciones mencionadas, pero no otras, por ejemplo:

pio_configure (Pio *p_pio, const pio_type_t ul_type, const uint32_t ul_mask, const uint32_t ul_attribute)

No puedo entender qué ul_attributey qué ul_typeson.


Aquí hay una clase GPIO que se implementa para AVR y SAM. Podría dar una pista de cómo usar los registros: github.com/mikaelpatel/Arduino-GPIO/blob/master/src/Hardware/…
Mikael Patel

Respuestas:


7

Si tiene una lectura de la sección 31 de la Hoja de datos, disponible desde aquí , las cosas pueden ser un poco más claras para usted.

Aquí hay un resumen de lo que sé:

PIO significa entrada / salida paralela y ofrece la funcionalidad para leer y escribir múltiples puertos de registro a la vez. Cuando la hoja de datos menciona un registro, por ejemplo PIO_OWER, la biblioteca Arduino tiene macros para acceder a ellos en este formato REG_PIO? _OWER where? es A, B, C o D para los diferentes puertos disponibles.

Todavía tiendo a usar la función lenta Arduino pinMode () para configurar la entrada / salida en los pines, ya que hace que el código sea más legible que las llamadas de registros basados ​​en acrónimos como REG_PIOC_OWER = 0xdeadbeef, pero luego uso los registros directos para configurar los pines para rendimiento / sincronización. Hasta ahora, no he hecho nada con la entrada, por lo que mis ejemplos están basados ​​en la salida.

Para un uso básico, usaría REG_PIO? _SODR para establecer líneas de salida altas y REG_PIO? _CODR para establecerlas bajas. Por ejemplo, REG_PIOC_SODR = 0x00000002 establecería el bit 1 (numerado desde cero) en PORTC (este es el pin 33 digital debido) alto. Todos los demás pines en PORTC permanecen sin cambios. REG_POIC_CODR = 0x00000002 establecería el bit 1 en PORTC bajo. Una vez más, todos los demás pines permanecerían sin cambios.

Como esto todavía no es óptimo, o está sincronizado si está trabajando con datos paralelos, hay un registro que le permite escribir los 32 bits de un puerto con una sola llamada. Estos son REG_PIO? _ODSR, por lo que REG_PIOC_ODSR = 0x00000002 ahora establecería el bit 1 en PORTC alto y todos los demás bits en PORTC se establecerían bajo instantáneamente en una sola instrucción de CPU.

Debido a que es poco probable que alguna vez se encuentre en una situación en la que necesite configurar los 32 bits de un puerto al mismo tiempo, necesitaría almacenar el valor actual de los pines, realizar una operación AND para enmascarar los que desea alterar, realice una operación OR para establecer las que desea establecer en alto, luego realice su escritura y nuevamente, y esto no es óptimo. Para superar esto, la CPU misma realizará el enmascaramiento por usted. Hay un registro llamado OWSR (registro de estado de escritura de salida) que enmascarará los bits que escriba en los ODSR que no coincidan con los bits establecidos en el OWSR.

Entonces, ahora si llamamos REG_PIOC_OWER = 0x00000002 (esto establece el bit 1 del OWSR alto) y REG_PIOC_OWDR = 0xfffffffd (esto borra todos los bits excepto el bit 1 del OWSR) y luego llamamos REG_PIOC_ODSR = 0x00000002 nuevamente, esta vez solo cambiaría el bit 1 de PORTC y todos los demás bits permanecen sin cambios. Preste atención al hecho de que OWER habilita cualquier bit que esté establecido en 1 en el valor que escribe y que OWDR deshabilita cualquier bit que esté establecido en 1 en el valor que escribe. Aunque entendí esto cuando lo leí, todavía me las arreglé para cometer un error de código al escribir mi primer código de prueba pensando que OWDR deshabilitó los bits que no estaban configurados en 1 en el valor que escribí.

Espero que esto al menos te haya ayudado a comprender el PIO de la CPU Due. Lee y juega, y si tienes más preguntas, intentaré responderlas.

Editar: Una cosa más ...

¿Cómo sabe qué bits de los PUERTOS corresponden a qué líneas digitales del Vencimiento? Mira esto: Debido Pinout


3

Hay una equivalencia bastante simple para el acceso directo directo al pin. A continuación se muestra un código de muestra que muestra cómo establecer un pin digital alto y luego bajo. El primero es para un Arduino Due, el segundo es para el Arduino Uno / Mega / etc.

const unsigned int imThePin = 10; //e.g. digital Pin 10

#ifdef _LIB_SAM_

    //First lets get the pin and bit mask - this can be done once at the start and then used later in the code (as long as the variables are in scope
    Pio* imThePort = g_APinDescription[imThePin].pPort; 
    unsigned int imTheMask = g_APinDescription[imThePin].ulPin; 

    //Lets set the pin high
    imThePort->PIO_SODR = imTheMask;
    //And then low
    imThePort->PIO_CODR = imTheMask;

#else

    //First lets get the pin and bit mask - this can be done once at the start and then used later in the code (as long as the variables are in scope
    volatile unsigned char* imThePort = portOutputRegister(digitalPinToPort(imThePin)); 
    unsigned char imTheMask = digitalPinToBitMask(imThePin);

    //Lets set the pin high
    *imThePort |= imTheMask;
    //Now low
    *imThePort &= ~imTheMask;

#endif

Todo lo que se necesita para hacer eso debe incluirse de manera predeterminada, y si no, #include <Arduino.h>debe ser suficiente para lograrlo.

En realidad, hay funciones disponibles que se pueden invocar una vez que tiene el Piopuntero para hacer la configuración / borrado / resistencias pullup / etc. usando llamadas de función de aspecto ligeramente más limpio. Se puede encontrar una lista completa en el archivo de cabecera.


0

Este es un ejemplo de código que muestra un led en el pin 33. Código tomado de arriba - muchas gracias por las explicaciones muy útiles :) Este es el comienzo de un proyecto para hablar con una pantalla táctil TFT con descarga de datos de píxeles de color de 16 bits que necesita Acceso rápido a los puertos. Creo que tengo el código correcto, particularmente la línea que establece el pin bajo. El led está felizmente parpadeando.

void setup() 
{
  pinMode(33, OUTPUT); 
  REG_PIOC_OWER = 0x00000002; 
  REG_PIOC_OWDR = 0xfffffffd; 
}

void loop() 
{
  REG_PIOC_ODSR = 0x00000002; 
  delay(1000);             
  REG_PIOC_ODSR = 0x00000000;    
  delay(1000);   
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.