C6 - Microcontroller Ports

De Proyectos
Saltar a: navegación, buscar

C6.0 - Introduction


I/O pins configuration: los pines de un microcontrolador pueden tener varias funciones

  • Parallel I/O
  • Alternative functions
    • UART (Universal asyncronous reciever/transmietter) - The UART can be used for serial communication between computers. It is asynchronous and allows for simultaneous communication in both directions.
    • SSI (Synchronous serial interface) - The SSI is alternately called serial peripheral interface (SPI). It is used to interface medium-speed I/O devices. In this book, we will use it to interface a graphics display. We could use SSI to interface a digital to analog converter (DAC) or a secure digital card (SDC).
    • I2C (Inter-integrated circuit) - I2C is a simple I/O bus that we will use to interface low speed peripheral devices.
    • Timer (Periodic interrupts, input capture, and output compare) - Input capture and output compare will be used to create periodic interrupts and measure period, pulse width, phase, and frequency.
    • PWM (Pulse width modulation) - PWM outputs will be used to apply variable power to motor interfaces. In a typical motor controller, input capture measures rotational speed, and PWM controls power. A PWM output can also be used to create a DAC.
    • ADC (Analog to digital converter, measure analog signals) - The ADC will be used to measure the amplitude of analog signals and will be important in data acquisition systems.
    • Analog comparator (Compare two analog signals) - The analog comparator takes two analog inputs and produces a digital output depending on which analog input is greater.
    • QEI (Quadrature encoder interface) - The QEI can be used to interface a brushless DC motor.
    • USB (Universal serial bus) - USB is a high-speed serial communication channel.
    • Ethernet (High-speed network) - The Ethernet port can be used to bridge the microcontroller to the Internet or a local area network.
    • CAN (Controller area network) - The CAN creates a high-speed communication channel between microcontrollers and is commonly found in automotive and other distributed control applications.


C6.1 - Stellaris LM4F120 and Tiva TM4C123 LaunchPad I/O Pins


Puertos Tiva Launchpad

C6-tm4c123-ports.gif

En la imagen de arriba se ven los puertos del TM4C123

Registro PCTL

IO

Ain

0

1

2

3

4

5

6

7

8

9

14

PA0

 

Port

U0Rx

 

 

 

 

 

 

CAN1Rx

 

 

PA1

 

Port

U0Tx

 

 

 

 

 

 

CAN1Tx

 

 

PA2

 

Port

 

SSI0Clk

 

 

 

 

 

 

 

 

PA3

 

Port

 

SSI0Fss

 

 

 

 

 

 

 

 

PA4

 

Port

 

SSI0Rx

 

 

 

 

 

 

 

 

PA5

 

Port

 

SSI0Tx

 

 

 

 

 

 

 

 

PA6

 

Port

 

 

I2C1SCL

 

M1PWM2

 

 

 

 

 

PA7

 

Port

 

 

I2C1SDA

 

M1PWM3

 

 

 

 

 

PB0

 

Port

U1Rx

 

 

 

 

 

T2CCP0

 

 

 

PB1

 

Port

U1Tx

 

 

 

 

 

T2CCP1

 

 

 

PB2

 

Port

 

 

I2C0SCL

 

 

 

T3CCP0

 

 

 

PB3

 

Port

 

 

I2C0SDA

 

 

 

T3CCP1

 

 

 

PB4

Ain10

Port

 

SSI2Clk

 

M0PWM2

 

 

T1CCP0

CAN0Rx

 

 

PB5

Ain11

Port

 

SSI2Fss

 

M0PWM3

 

 

T1CCP1

CAN0Tx

 

 

PB6

 

Port

 

SSI2Rx

 

M0PWM0

 

 

T0CCP0

 

 

 

PB7

 

Port

 

SSI2Tx

 

M0PWM1

 

 

T0CCP1

 

 

 

PC4

C1-

Port

U4Rx

U1Rx

 

M0PWM6

 

IDX1

WT0CCP0

U1RTS

 

 

PC5

C1+

Port

U4Tx

U1Tx

 

M0PWM7

 

PhA1

WT0CCP1

U1CTS

 

 

PC6

C0+

Port

U3Rx

 

 

 

 

PhB1

WT1CCP0

USB0epen

 

 

PC7

C0-

Port

U3Tx

 

 

 

 

 

WT1CCP1

USB0pflt

 

 

PD0

Ain7

Port

SSI3Clk

SSI1Clk

I2C3SCL

M0PWM6

M1PWM0

 

WT2CCP0

 

 

 

PD1

Ain6

Port

SSI3Fss

SSI1Fss

I2C3SDA

M0PWM7

M1PWM1

 

WT2CCP1

 

 

 

PD2

Ain5

Port

SSI3Rx

SSI1Rx

 

M0Fault0

 

 

WT3CCP0

USB0epen

 

 

PD3

Ain4

Port

SSI3Tx

SSI1Tx

 

 

 

IDX0

WT3CCP1

USB0pflt

 

 

PD4

USB0DM

Port

U6Rx

 

 

 

 

 

WT4CCP0

 

 

 

PD5

USB0DP

Port

U6Tx

 

 

 

 

 

WT4CCP1

 

 

 

PD6

 

Port

U2Rx

 

 

M0Fault0

 

PhA0

WT5CCP0

 

 

 

PD7

 

Port

U2Tx

 

 

 

 

PhB0

WT5CCP1

NMI

 

 

PE0

Ain3

Port

U7Rx

 

 

 

 

 

 

 

 

 

PE1

Ain2

Port

U7Tx

 

 

 

 

 

 

 

 

 

PE2

Ain1

Port

 

 

 

 

 

 

 

 

 

 

PE3

Ain0

Port

 

 

 

 

 

 

 

 

 

 

PE4

Ain9

Port

U5Rx

 

I2C2SCL

M0PWM4

M1PWM2

 

 

CAN0Rx

 

 

PE5

Ain8

Port

U5Tx

 

I2C2SDA

M0PWM5

M1PWM3

 

 

CAN0Tx

 

 

PF0

 

Port

U1RTS

SSI1Rx

CAN0Rx

 

M1PWM4

PhA0

T0CCP0

NMI

C0o

 

PF1

 

Port

U1CTS

SSI1Tx

 

 

M1PWM5

PhB0

T0CCP1

 

C1o

TRD1

PF2

 

Port

 

SSI1Clk

 

M0Fault0

M1PWM6

 

T1CCP0

 

 

TRD0

PF3

 

Port

 

SSI1Fss

CAN0Tx

 

M1PWM7

 

T1CCP1

 

 

TRCLK

PF4

 

Port

 

 

 

 

M1Fault0

IDX0

T2CCP0

USB0epen

 

 


En el microcontrolador hay diferentes regitros que configuran varios aspectos o funciones de los pines. En la tabla superior se muestra el registro GPIOPCTL (encargado de las funciones altrenativas de los pines)
EXPLICAR TABLA

  • En el registro GPIOPCTL se configuran las funciones altrenativas de los pines (0 significa que se configura el pine como un puerto I/O normal).
  • Los pines que van de PC3-PC0 no salen en la tabla porque estan reservados para el debugger JTAG y no se pueden usar como puertos I/O normales.
  • Algunas funciones altrenativas solo pueden estar en un pin determinado y otras pueden estar en varios pines (por ejemplo CAN0Rx puede estar mapeado en los pines PB4, PE4 o PF0)


Tiva Launchpad

C6-launchpad.jpg

  • Esta es la placa Tiva LaunchPad basada en el chip LM4F120H5QR o TM4C123GH6PM.
  • Incluye integrado un In-Circuit Debug Interface (ICDI) que nos permite programar y hacer debug al controlador.
  • Un puerto USB sirve para el ICDI y el otro para desarrollar aplicaciones que se comuniquen por usb.
  • El switch de power permite que la placa se alimente por el usb del ICDI o por el otro USB.


Esquema Tiva Launchpad

C6-esq-launchpad.gif

  • Pines PA1-PA0 - función UART - se usa para el debugger
  • Pines PD4-PD5 - conexión USB
  • Pines PC3-PC0 - JTAG debugger
  • PB6 conectado a PD0 y PB7 conectado a PD1
    • Para usarlos individualmente se tiene que quitar R9 y R10
  • La placa tiene dos switches de logica negativa (PF0 y PF4) y requieren que se active la resistencia pull-up interna
  • La placa tiene 3 leds de colores de logica positiva (PF3-PF1)


C6.2 - Conecptos básicos de los puertos de Entrada y Salida


C6-puerto.gif

  • En esta imagen se puede ver como funciona un puerto en las operaciones de lectura y escritura.
  • En el ciclo de lectura el triestado pasa las señales input que estan en los pines al bus de datos.
  • En el ciclo de escritura el microcontrolador pone la información en el bus de datos y esa información se pasa al flip-flop de tipo D mediante una señal de reloj
  • El flip-flop que pone "Write to port direction register" es el encargado de hacer que el puerto sea de entrada o salida.
    • Cuando en el registro de dirección ponemos un 0 se deshabilita el triestado de salida y las señales del puerto pasan al bus de datos
    • Cuando en el registro de dirección ponemos un 1 se habilita el triestado de salida y entonces las señales del microcontrolador pasan al puerto
    • En el ciclo de escritura (salida) también está habilitado la lectura. Podemos leer el valor que acabamos de escribir en el puerto


C6.3 - Programación de los I/O y el Registro de Dirección


Introducción a los registros
Port F

  • Direction Register - 0x40025400
    • Tiene 5 bits que nos interesan, del bit 4 al bit 0
    • Cada bit indica si un pin del puerto F es input/output
      • 0 si el pin es input
      • 1 si el pin es output
    • El en Tiva Launchpad
      • Pin 5 y Pin 1 son los switches (inputs)
      • Pin 2, Pin 3 y Pin 4 son el led RGB (output)


  • Enable Register - 0x4002551C
    • Tiene 5 bits que nos interesan, del bit 4 al bit 0
    • Cada bit activa un pin del puerto F
      • 1 para activar el pin
      • 0 para desactivar el pin


Tabla de algunos puertos paralelos (cada registro tiene 32 bits)

Address

7

6

5

4

3

2

1

0

Name

$400F.E108

--

--

GPIOF

GPIOE

GPIOD

GPIOC

GPIOB

GPIOA

SYSCTL_RCGC2_R

$4000.43FC

DATA

DATA

DATA

DATA

DATA

DATA

DATA

DATA

GPIO_PORTA_DATA_R

$4000.4400

DIR

DIR

DIR

DIR

DIR

DIR

DIR

DIR

GPIO_PORTA_DIR_R

$4000.4420

SEL

SEL

SEL

SEL

SEL

SEL

SEL

SEL

GPIO_PORTA_AFSEL_R

$4000.4510

PUE

PUE

PUE

PUE

PUE

PUE

PUE

PUE

GPIO_PORTA_PUR_R

$4000.451C

DEN

DEN

DEN

DEN

DEN

DEN

DEN

DEN

GPIO_PORTA_DEN_R

$4000.4524

1

1

1

1

1

1

1

1

GPIO_PORTA_CR_R

$4000.4528

0

0

0

0

0

0

0

0

GPIO_PORTA_AMSEL_R

$4000.53FC

DATA

DATA

DATA

DATA

DATA

DATA

DATA

DATA

GPIO_PORTB_DATA_R

$4000.5400

DIR

DIR

DIR

DIR

DIR

DIR

DIR

DIR

GPIO_PORTB_DIR_R

$4000.5420

SEL

SEL

SEL

SEL

SEL

SEL

SEL

SEL

GPIO_PORTB_AFSEL_R

$4000.5510

PUE

PUE

PUE

PUE

PUE

PUE

PUE

PUE

GPIO_PORTB_PUR_R

$4000.551C

DEN

DEN

DEN

DEN

DEN

DEN

DEN

DEN

GPIO_PORTB_DEN_R

$4000.5524

1

1

1

1

1

1

1

1

GPIO_PORTB_CR_R

$4000.5528

0

0

AMSEL

AMSEL

0

0

0

0

GPIO_PORTB_AMSEL_R

$4000.63FC

DATA

DATA

DATA

DATA

JTAG

JTAG

JTAG

JTAG

GPIO_PORTC_DATA_R

$4000.6400

DIR

DIR

DIR

DIR

JTAG

JTAG

JTAG

JTAG

GPIO_PORTC_DIR_R

$4000.6420

SEL

SEL

SEL

SEL

JTAG

JTAG

JTAG

JTAG

GPIO_PORTC_AFSEL_R

$4000.6510

PUE

PUE

PUE

PUE

JTAG

JTAG

JTAG

JTAG

GPIO_PORTC_PUR_R

$4000.651C

DEN

DEN

DEN

DEN

JTAG

JTAG

JTAG

JTAG

GPIO_PORTC_DEN_R

$4000.6524

1

1

1

1

JTAG

JTAG

JTAG

JTAG

GPIO_PORTC_CR_R

$4000.6528

AMSEL

AMSEL

AMSEL

AMSEL

JTAG

JTAG

JTAG

JTAG

GPIO_PORTC_AMSEL_R

$4000.73FC

DATA

DATA

DATA

DATA

DATA

DATA

DATA

DATA

GPIO_PORTD_DATA_R

$4000.7400

DIR

DIR

DIR

DIR

DIR

DIR

DIR

DIR

GPIO_PORTD_DIR_R

$4000.7420

SEL

SEL

SEL

SEL

SEL

SEL

SEL

SEL

GPIO_PORTD_AFSEL_R

$4000.7510

PUE

PUE

PUE

PUE

PUE

PUE

PUE

PUE

GPIO_PORTD_PUR_R

$4000.751C

DEN

DEN

DEN

DEN

DEN

DEN

DEN

DEN

GPIO_PORTD_DEN_R

$4000.7524

CR

1

1

1

1

1

1

1

GPIO_PORTD_CR_R

$4000.7528

0

0

AMSEL

AMSEL

AMSEL

AMSEL

AMSEL

AMSEL

GPIO_PORTD_AMSEL_R

$4002.43FC

 

 

DATA

DATA

DATA

DATA

DATA

DATA

GPIO_PORTE_DATA_R

$4002.4400

 

 

DIR

DIR

DIR

DIR

DIR

DIR

GPIO_PORTE_DIR_R

$4002.4420

 

 

SEL

SEL

SEL

SEL

SEL

SEL

GPIO_PORTE_AFSEL_R

$4002.4510

 

 

PUE

PUE

PUE

PUE

PUE

PUE

GPIO_PORTE_PUR_R

$4002.451C

 

 

DEN

DEN

DEN

DEN

DEN

DEN

GPIO_PORTE_DEN_R

$4002.4524

 

 

1

1

1

1

1

1

GPIO_PORTE_CR_R

$4002.4528

 

 

AMSEL

AMSEL

AMSEL

AMSEL

AMSEL

AMSEL

GPIO_PORTE_AMSEL_R

$4002.53FC

 

 

 

DATA

DATA

DATA

DATA

DATA

GPIO_PORTF_DATA_R

$4002.5400

 

 

 

DIR

DIR

DIR

DIR

DIR

GPIO_PORTF_DIR_R

$4002.5420

 

 

 

SEL

SEL

SEL

SEL

SEL

GPIO_PORTF_AFSEL_R

$4002.5510

 

 

 

PUE

PUE

PUE

PUE

PUE

GPIO_PORTF_PUR_R

$4002.551C

 

 

 

DEN

DEN

DEN

DEN

DEN

GPIO_PORTF_DEN_R

$4002.5524

 

 

 

1

1

1

1

CR

GPIO_PORTF_CR_R

$4002.5528

 

 

 

0

0

0

0

0

GPIO_PORTF_AMSEL_R

 

 

 

 

 

 

 

 

 

 

 

31-28

27-24

23-20

19-16

15-12

11-8

7-4

3-0

 

$4000.452C

PMC7

PMC6

PMC5

PMC4

PMC3

PMC2

PMC1

PMC0

GPIO_PORTA_PCTL_R

$4000.552C

PMC7

PMC6

PMC5

PMC4

PMC3

PMC2

PMC1

PMC0

GPIO_PORTB_PCTL_R

$4000.652C

PMC7

PMC6

PMC5

PMC4

0x1

0x1

0x1

0x1

GPIO_PORTC_PCTL_R

$4000.752C

PMC7

PMC6

PMC5

PMC4

PMC3

PMC2

PMC1

PMC0

GPIO_PORTD_PCTL_R

$4002.452C

 

 

PMC5

PMC4

PMC3

PMC2

PMC1

PMC0

GPIO_PORTE_PCTL_R

$4002.552C

 

 

 

PMC4

PMC3

PMC2

PMC1

PMC0

GPIO_PORTF_PCTL_R

$4000.6520

LOCK (write 0x4C4F434B to unlock, other locks) (reads 1 if locked, 0 if unlocked)

GPIO_PORTC_LOCK_R

$4000.7520

LOCK (write 0x4C4F434B to unlock, other locks) (reads 1 if locked, 0 if unlocked)

GPIO_PORTD_LOCK_R

$4002.5520

LOCK (write 0x4C4F434B to unlock, other locks) (reads 1 if locked, 0 if unlocked)

GPIO_PORTF_LOCK_R


Código inicialización puertos/pines

  • Para inicializar un puerto para uso general usamos siete pasos.
  • Los pasos del 2 al 4 solo son necesarios para los microcontroladores de LM4F/TM4C
  • Pasos
    • Primer paso - Activamos el reloj del puerto
    • Segundo paso - Desbloqueamos puerto
    • Tercer paso - Configuramos si es anologico o digital el pin
    • Cuarto paso - Configuramos las funciones avanzadas digitales del pin (Registro PCTL)
    • Quinto paso - Configuramos la direccion del pin (entrada/salida)
    • Sexto paso - Configuramos funciones alternativas, si la shay
    • Séptimo paso - Activamos el pin (Registro Enable)


#include "tm4c123ge6pm.h"
unsigned long In;  // input from PF4
unsigned long Out; // output to PF2 (blue LED)
//   Function Prototypes
void PortF_Init(void);
// 3. Subroutines Section
// MAIN: Mandatory for a C Program to be executable
int main(void){    // initialize PF0 and PF4 and make them inputs
 PortF_Init();    // make PF3-1 out (PF3-1 built-in LEDs)
 while(1){
   In = GPIO_PORTF_DATA_R&0x10;   // read PF4 into Sw1
   In = In>>2;                    // shift into position PF2
   Out = GPIO_PORTF_DATA_R;
   Out = Out&0xFB;
   Out = Out|In;
   GPIO_PORTF_DATA_R = Out;        // output
 }
}
// Subroutine to initialize port F pins for input and output
// PF4 is input SW1 and PF2 is output Blue LED
// Inputs: None
// Outputs: None
// Notes: ...
void PortF_Init(void){ volatile unsigned long delay;
 SYSCTL_RCGC2_R |= 0x00000020;     // 1) activate clock for Port F
 delay = SYSCTL_RCGC2_R;           // allow time for clock to start
 GPIO_PORTF_LOCK_R = 0x4C4F434B;   // 2) unlock GPIO Port F
 GPIO_PORTF_CR_R = 0x1F;           // allow changes to PF4-0
 // only PF0 needs to be unlocked, other bits can't be locked
 GPIO_PORTF_AMSEL_R = 0x00;        // 3) disable analog on PF
 GPIO_PORTF_PCTL_R = 0x00000000;   // 4) PCTL GPIO on PF4-0
 GPIO_PORTF_DIR_R = 0x0E;          // 5) PF4,PF0 in, PF3-1 out
 GPIO_PORTF_AFSEL_R = 0x00;        // 6) disable alt funct on PF7-0
 GPIO_PORTF_PUR_R = 0x11;          // enable pull-up on PF0 and PF4
 GPIO_PORTF_DEN_R = 0x1F;          // 7) enable digital I/O on PF4-0
}


En el código de arriba se muestra un pequeño programa que iniciliza e interactua con algunos puertos que son los que estan asignados al switch de la placa y a los leds.

  • Lo primero con lo que nos encontramos es #include "tm4c123ge6pm.h"
    • Este include tiene las definiciones de los registros para que sea más fácil utlizarlos
    • Por ejemplo, GPIO_PORTF_DATA_R , este define asigna la dirección de memoria del registro para que en vez de que tengamos que poner esa dirección en nuestro código, pongamos algo más fácil de memorizar
  • Luego vemos una declaración de variables (que nos serviran para guardar el estado de cada pin) y vemos una función que se llama PortF_Init(). Esta función es la encargada de inicializar los pines que vamos a necesitar en nuestro programa (en este caso inicializa el Puerto F)
    • Primer paso - activar el reloj del puerto F SYSCTL_RCGC2_R |= 0x00000020;
      • Cada dispositivo tiene un reloj que puede activarse
      • El bit 5 de este registro se activa para activar el reloj del puerto F
    • Ponemos un delay para asegurarnos de que el clock se ha iniciado delay = SYSCTL_RCGC2_R;
    • Segundo paso - desbloqueamos el puerto a utilizar GPIO_PORTF_LOCK_R = 0x4C4F434B;
      • Esto solo es necesario para los pines PC3-0, PD7 y PF0
      • El número hexadecimal que se asigna al registro de desbloqueo lo indica la tabla que he puesto al final de esta explicación
      • Luego de desbloquearlo tenemos que activar los bits del GPIO_PORTF_CR_R (no se para que sirve este registro, pero se tiene que hacer así)
    • Tercer paso - deshabilitar la función analógica (en nuestro programa queremos que los pines sean digitales), por lo tanto se escribe en el registro GPIO_PORTF_AMSEL_R = 0x00
    • Cuarto paso - los pines serán digitales y su función será de I/O, por lo tanto se selecciona la función I/O GPIO_PCTL_R = 0x00000000 (Esto es lo que se ve en la tabla de la sección 6.1)
    • Quinto paso - configuramos los pines que seran input y los que seran output GPIO_DIR_R = 0x0E
      • En nuestro código el pin 4 y el 0 son input (switches) y los pines 1, 2 y 3 son outpus (leds). 0 para input, 1 para output, entonces queda 01110 que en hexa es E
    • Sexto paso - deshabilitamos las funciones alternativas en el registro ASFEL GPIO_PORTF_AFSEL_R = 0x00
    • Séptimo paso - activamos el registro de datos de los pines que vamos a usar GPIO_PORTF_DEN_R = 0x1F
    • En este caso necesitamos de las pull-up internas, por lo tanto las activamos GPIO_PORTF_PUR_R = 0x11



Al acabar la inicialización viene el programa en si

 while(1){
   In = GPIO_PORTF_DATA_R&0x10;   // read PF4 into Sw1
   In = In>>2;                    // shift into position PF2
   Out = GPIO_PORTF_DATA_R;
   Out = Out&0xFB;
   Out = Out|In;
   GPIO_PORTF_DATA_R = Out;        // output
 }


  • El bluce while con condicion 1 sirve para ejecutar el bucle indefinidamente
  • En el registro GPIO_PORTF_DARA_R encontramos los valores de las salidas/entradas de los pines del puerto F
    • Utilizamos una máscara (0x10) para seleccionar solo el pin que nos interesa, en este caso el PF4 que es el switch 1
    • Guardamos el valor del puerto en la variable In.
  • Se mueve dos posiciones el valor del pin 4 porque se lo asignaremos al pin PF2 que es donde esta el led


Friendly code

Crear friendly code significa leer o escribir información de los registros sin alterar los bits que no sean los que necesitamos. Para ello se utilizan las máscaras
Ejemplo:

Escribir 1 (hacer un set) en el registro data. Para ello utilizamos la operación OR:

  • b | 1 = 1
  • b | 0 = b

Por lo tanto si tenemos un registro de 8 bits en donde queremos poner un 1 en el bit 4 a nuestro registro le haremos una OR con una máscara:

   b7 b6 b5 b4 b3 b2 b1 b0 -> Registro de 8 bits
|  0  0  0  1  0  0  0  0  -> Máscara
   b7 b6 b5 1  b3 b2 b1 b0 -> Esto es lo que escribiremos en el registro

En el ejemplo de arriba vemos que al hacer una OR con una máscara 0x10 al registro, ponemos el bit 4 en 1

Escribir 0 (hacer un clear) en el registro data. Para ello hacemos lo mismo que para hacer un set pero en vez de una OR usamos una AND:

  • b & 0 = 0
  • b & 1 = b

La máscara resultante la podemos escribir tal cual no sale o podemos escribirla en negado, ejemplo:

Queremos hacer clear en el bit 4 -> la máscara será 11101111 que pasado a hex es 0xEF
Si negamos esta máscara obtendremos -> 0xEF = ~00010000 = ~0x10