¿Cómo configurar un puerto ARM GPIO (STR9) para una función alternativa?

2

Como soy nuevo en la programación de microcontroladores procedentes del mundo C ++, he estado estudiando cómo hacer que el código se ejecute en una placa de microcontroladores para trabajar con muchas entradas y salidas.

Para el primer proyecto, estoy trabajando en un chip ARM9 (STR912FAW44) con Rowley Crossworks para que ARM programe mi placa. Entiendo que tengo que configurar el puerto 7.3 en modo de salida para conducir un LED. También entiendo que el puerto GPIO tiene múltiples modos en este pin, por defecto a GP Input. También sé que la configuración de la salida 1 alternativa es la salida GP.

Ahora el manual para el chip dice:

  

Hay hasta 80 pines GPIO disponibles en 10 puertos de E / S para dispositivos de 128 pines y 144 bolas, y   hasta 40 pines GPIO en 5 puertos de E / S para dispositivos de 80 pines. Cada pin GPIO por defecto   (durante y justo después de una condición de reinicio) está en modo de entrada de alta impedancia, y algunos GPIO   Los pines se enrutan adicionalmente a ciertas entradas de funciones periféricas. El firmware de la CPU puede inicializar los pines GPIO para tener funciones de entrada o salida alternativas como se indica en la Tabla 8.

Esto suena maravilloso. La pregunta es ¿cómo puedo hacer que el puerto acepte una función diferente?

Tengo un código de muestra para una placa similar, pero diferente, donde el LED (el más fácil de probar) está en el puerto 9, pero esto no funciona cuando se ajusta al puerto 7 como esperaba.

Aquí está la muestra:

void
ctl_board_init(void)
{
  // leds are connected to GPIO9.0-GPIO9.3
  SCU_PCGR1 |= SCU_PCGR1_GPIO9_MASK; // turn on GPIO9
  SCU_PRR1 |= SCU_PRR1_RST_GPIO9_MASK;  
  GPIO9_DIR = 0x01; // select output direction
}

void 
ctl_board_on_button_pressed(CTL_ISR_FN_t buttonFn)
{
}

void
ctl_board_set_leds(unsigned v)
{
  *((&GPIO9_DATA)+(0x01<<2)) = v ? 0x01 : 0;   
}

Las macros provienen de archivos de encabezado, pero ¿alguien puede ayudarme a encontrar una referencia a los bits que debo configurar para manejar el puerto GPIO 7.3 como salida?

    
pregunta Wouter Simons

3 respuestas

4

La familia de microcontroladores STR91x tiene periféricos muy flexibles. Desafortunadamente, esta flexibilidad los hace algo complicados de configurar. Mi sugerencia es comenzar por descargar el STR91xFA Firmware Library de ST.com. Una vez que tenga la biblioteca vinculada a su proyecto, debe hacer algo similar a lo siguiente:

void InitGPIO7( void )
{
   GPIO_InitTypeDef GPIO_InitStructure;

   /* Enable the GPIO7 clock */
   SCU_APBPeriphClockConfig(__GPIO7, ENABLE);

   /* Initialize the GPIO port */
   GPIO_DeInit(GPIO7);

   /* Configure pin GPIO7.3 */
   GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput;
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
   GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull;
   GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Disable;
   GPIO_InitStructure.GPIO_Alternate = GPIO_OutputAlt1;
   GPIO_Init (GPIO7, &GPIO_InitStructure);
}

Tenga en cuenta que esto no se ha probado, pero debería estar bastante cerca.

    
respondido por el semaj
1

De mirar la hoja de datos (13742.pdf ), parece que para los pines GPIO 0-7 necesita establecer el bit apropiado en los registros SCU_GPIOTYPE y posiblemente otros.

  

La unidad de control del sistema GPIO registra los pines GPIO en P0   a través de P7 tiene múltiples entradas y salidas   funciones alternativas. Tu seleccionas estos   utilizando la unidad de control del sistema (SCU)   registros También se utilizan registros de la SCU.   para seleccionar colector abierto o push-pull   Operación y configuración del puerto 4 pines.   para su uso como entradas analógicas. Pines GPIO en   P8 a P9 solo se multiplexan con   EMI y no tienen salida o entrada SCU   registros de control. Todos los puertos tienen   SCU_GPIOTYPE se registra para seleccionar   Colector abierto o Push / Pull   configuración.

    
respondido por el Toby Jaffey
0

Hay una descripción detallada en la hoja de datos de STR91xF: es complicada, pero no tan complicada como las bibliotecas ST lo hacen parecer. Dados los #defines y estructuras enumerados en el final, para encender por ejemplo GPIO4:

SCU->PCGR1 |= __GPIO4;                      // switch the port on.
SCU->PCGRO &=~ (u32)__GPIO4;                // reset the device
SCU->PRR1 |= __GPIO4;                       // peripheral not held in Reset

Luego, puedes configurar el puerto utilizando una combinación de

   GPIO4->DDR 
   SCU->GPIOOUT[4]
   SCU->GPIOIN[4]
   SCU->GPIOTYPE[4]

(y GPIO4- > DR [n] para configurar y leer los pines)

GPIOn - > DDR es 8 bits, los bits 7: 0 corresponden a los pines 7: 0. cualquier bit establecido hace que sea su               pin correspondiente una salida, el valor predeterminado es cero, todas las entradas.

Los registros de la SCU también son máscaras de bits, de la siguiente manera:

GPIOTYPE [número_puerto] es 8 bits, con el bit 7: 0 correspondiente al pin 7: 0. Cualquier conjunto de bits                       Realiza sus correspondientes pines de salida de colector abierto. El valor predeterminado es todo                       cero (push-pull)

GPIOIN [número de puerto] es de 8 bits. Cualquier bit establecido tiene la entrada enrutada a alguna u otra                     Función de entrada periférica interna, como se detalla en una tabla grande en                     La hoja de datos, depende del dispositivo. NOTA: Incluso cuando está conectado a                     un periférico interno, también puede leerlo como una entrada general.                     El valor predeterminado es todo cero, entrada de propósito general simple

GPIOOUT [número de puerto] es de 16 bits, cada par de bits corresponde a un pin, por lo que los bits                      14 y 15 controlan el pin 7, los bits 0 y 1 controlan el pin 0. Cero significa                      Entrada GPIO ordinaria, 1 es salida GPIO normal, 2 y 3 son alternativas                      Salidas desde periféricos internos. (Ver tabla grande en datos STR9xx                      hoja)

Entonces, para configurar GPIO4 de modo que los pines 0 y 1 sean salidas, con 0 como colector abierto, y los pines restantes son entradas, haz:

GPIO4->DDR = 0x03;          //  0  0   0  0   0  0   1  1     pins 0 and 1 are output
SCU->GPIOOUT[4] = 0x0005;   // 00 00  00 00  00 00  01 01     pins 0 and 1 are Alt1 output
SCU->GPIOTYPE[4] = 0x01;    //  0  0   0  0   0  0   0  1     pin 0 open collector
SCU->GPIOIN[4] = 0x00;      // no alternate inputs connected

Para configurar / leer realmente los pines del puerto, STR9 tiene un sistema de memoria asignada donde se enmascaran los pines por dirección y valor, para que pueda escribir solo los pines que desee sin tener que hacer demasiado ORing de argumentos. P.ej.

GPIO4->DR[GPIO_Pin_1 << 2] = GPIO_Pin_1; //sets pin1 output to high.
x = GPIO4->DR[GPIO_Pin_3 << 2];          //reads pin3 
y = GPIO4->DR[(GPIO_Pin_3 | GPIO_Pin_4) << 2];  // reads pins 3 and 4

y así sucesivamente.

Los símbolos utilizados anteriormente se reducen a:

#define __GPIO0 0x4000
#define __GPIO1 0x8000
#define __GPIO2 0x10000
#define __GPIO3 0x20000
#define __GPIO4 0x40000
#define __GPIO5 0x80000
#define __GPIO6 0x100000
#define __GPIO7 0x200000
#define __GPIO8 0x400000
#define __GPIO9 0x800000

typedef struct
{
  vu32 CLKCNTR;    
  vu32 PLLCONF;    
  vu32 SYSSTATUS;  
  vu32 PWRMNG;     
  vu32 ITCMSK;     
  vu32 PCGRO;      
  vu32 PCGR1;      
  vu32 PRR0;       
  vu32 PRR1;       
  vu32 MGR0;       
  vu32 MGR1;       
  vu32 PECGR0;     
  vu32 PECGR1;     
  vu32 SCR0;       
  vu32 SCR1;       
  vu32 SCR2;       
  u32 EMPTY1;
  vu32 GPIOOUT[8];   
  vu32 GPIOIN[8];   
  vu32 GPIOTYPE[10]; 
  vu32 GPIOEMI;      
  vu32 WKUPSEL;      
  u32 EMPTY2[2];
  vu32 GPIOANA;      
} SCU_TypeDef;

typedef struct
{
  vu8 DR[1021];     /* Data Register                    */
  vu32 DDR;         /* Data Direction Register          */
} GPIO_TypeDef;

// #define AHB_BASE   (0x58000000)              // unbuffered
#define AHB_BASE   (0x48000000)              // buffered

// #define __APB1_BASE          0x5C000000                // unbuffered
#define __APB1_BASE          0x4C000000                // buffered

#define __SCU_BASE           (__APB1_BASE + 0x2000)
#define SCU                  ((SCU_TypeDef *)__SCU_BASE)

#define GPIO0_OFFSET     (0x00006000)
#define GPIO0_OFFSET     (0x00007000)
// ...
#define GPIO4_OFFSET     (0x0000A000)

#define GPIO4   (AHB_BASE + GPIO4_OFFSET)


#define GPIO_Pin_None 0x00
#define GPIO_Pin_0    0x01
#define GPIO_Pin_1    0x02
#define GPIO_Pin_2    0x04
#define GPIO_Pin_3    0x08
#define GPIO_Pin_4    0x10
#define GPIO_Pin_5    0x20
#define GPIO_Pin_6    0x40
#define GPIO_Pin_7    0x80
#define GPIO_Pin_All  0xFF
    
respondido por el user3281

Lea otras preguntas en las etiquetas