Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Ingeniería Electrónica
SEMÁFORO
Estructuras Computacionales
Presentado por:
Presentado a:
Sede Manizales
Manizales, Colombia
30 de junio de 2020
1
STM32L476
Interrupciones
Interrupción externa:
30 de junio de 2020
2
UART -> UNIVERSAL ASYNCHRONOUS RECEIVER TRANSMITTER
El protocolo UART utiliza comunicación asíncrona, lo que significa que los datos
pueden trasmitirse en cualquier instante, y no hay ninguna coordinación temporal
estricta entre TX y RX.
El dispositivo UART que va a transmitir los datos recibe los datos de un bus de
datos. El bus de datos se utiliza para enviar datos a UART por otro dispositivo
como una CPU, memoria o microcontrolador. Los datos se transfieren desde el
bus de datos en forma paralela al dispositivo UART que los transmite. Después de
que el dispositivo UART transmisor obtiene los datos paralelos del bus de datos,
añade un bit de inicio, un bit de paridad y un bit de parada, creando el paquete de
datos. A continuación, el paquete de datos se emite en serie, bit a bit en el pin Tx.
El dispositivo UART receptor lee el paquete de datos bit a bit en su pin Rx, y luego
convierte los datos de nuevo en forma paralela y elimina el bit de inicio, el bit de
paridad y los bits de parada. Finalmente, transfiere el paquete de datos en paralelo
al bus de datos del extremo receptor.
Los datos transmitidos por la UART están organizados en paquetes. Cada paquete
contiene 1 bit de inicio, 5 a 9 bits de datos, un bit de paridad (opcional), y 1 o 2 bits de
parada:
30 de junio de 2020
3
Planteamiento del Problema:
Figura1
Puertos a utilizar:
Vehicular Peatonal
Rojo PA5 Rojo PB6
ÁmbarPA6 Verde PC7
Verde PA7 Botón PC13
30 de junio de 2020
4
Solución:
Máquina de Estados
La Máquina de Estados en un modelo del comportamiento de un sistema,
donde un conjunto de estados sirve de intermediarios entre la relación de
entradas y salidas que dependen no solo de las señales de entrada
actuales sino también de las anteriores.
Para este problema se implementó una posible máquina de estados donde
se incluyen ambos semáforos, vehiculas y peatonal
Figura2
30 de junio de 2020
5
Como se puede observar en la figura 2(Maquina de estados del semáforo), parte
de un estado inicial y en este problema el cambio de estados sucede cada
determinado periodo de tiempo sin necesidad de alguna señal externa. El
semáforo que se visualiza en la parte Izquierda de cada circulo hace referencia al
semáforo vehicular, mientras el que esta en la posición derecha del circulo hace
referencia al semáforo peatonal.
Ahora, cuando se agrega a la máquina la señal externa o el botón se identifica el
estado que corresponde a la condición y el que corresponde al nuevo estado al
que se va a cambiar, estos se conectan con una flecha ligada a el botón (lo que
representa que esa será la secuencia Botón).
Código:
int boton=1;
int con=0;
int t;
const uint8_t mensaje[] = "SVHR-SPTG\n\rSVHRA-SPTR\n\rSVHG-SPTR\n\rSVHA-
SPTR\n\r";
/*************************************************
* function declarations
*************************************************/
int main(void);
void GPIO_init(void);
void Ext_init(void);
void TIMER_init(void);
void UART_init(void);
void semaforo(void);
/*************************************************
30 de junio de 2020
6
boton: Es una variable que se pone en 0(cero) en el momento en que se
presiona el botón y se limpia con 1.
con: Es la base de tiempo del sistema, esta, va contando el tiempo en el
que se ha estado ejecutando el código y permitirá saber cuando debe
cambiar el estado.
t: Es una variable que va almacenando el tiempo actual al momento de
hacer un cambio de estados.
const: Es una variable que almacena el mensaje
GPIO_init(): Inicializa las entradas y salidas que se desean de los puertos y
los pines.
Ext_init(): Inicializa la interrupcion externa.
Timer_init(): Inicializa el Timer como base de tiempo.
USART_init(): Inicializar le protocolo de comunicaciones USART
void TIM2_IRQHandler(void)
{
void EXTI15_10_IRQHandler(void)
{
//Check if the interrupt came from exti13
if(EXTI->PR1 & (1 <<13)) {
boton=0;
// Clear pending bit
EXTI->PR1 = 0x00002000;
30 de junio de 2020
7
}
}
Se adiciona el botón que modifica el estado de los semáforos. Para que sea
detectado en cualquier momento de la ejecución del código se diseñó como una
interrupción externa que al ser ejecutada revisa en qué momento del tiempo se
encuentra la secuencia para identificar si está en el estado adecuado
(determinado como una de las condiciones en el ejercicio), hacer la bandera botón
igual a cero y que se haga el cambio de estado.
Este cambio solo se logra visualizar utilizando elementos electrónicos como leds,
debido a la situación actual no se cuentan con estos componentes a disposición,
sin embargo, el botón que esta conectado en la tarjeta logra hacer el cambio, pero
no fue posible mostrarlo en pantalla.
4. GPIO_init()
void GPIO_init(void){
// Se habilitan los relojes encargados de los puertos GPIO A,B,C.
// Enable GPIOA, GPIOB and GPIOC Peripheral Clock (bit 0 and 2
inAHB2ENR register)
RCC->AHB2ENR |= 0x00000007;
//se definen los pines de salida para los leds que simulan el
semaforo.
/*led rojo semaforo vehicular ---> salida GPIOA pin 5
*led amarillo semaforo vehicular ---> salida GPIOB pin 5
* led verde semaforo vehicular ---> salida GPIOC pin 7
* led rojo semaforo peatonal ---> salida GPIOA pin 7
* led verde semaforo peatonal ---> salida GPIOA pin 6
*/
30 de junio de 2020
8
// Make GPIOC Pin13 as input pin (bits 27:26 in MODER register)
GPIOC->MODER &= 0xF3FFFFFF; // Write 00 to bits 27, 26
for P13
// Make GPIOA Pin 2,3 as alternate pin (bits 1:0 in MODER register)
GPIOA->MODER |= 0x000000A0; //Write 10 to bits 4,5,6,7
for P2 and P3
// Set GPIOA Pin2,3 in high speed mode
GPIOA->OSPEEDR |= 0x000000A0; //Write 10 to bits 4,5,6,7
for P2 and P3
// Choose AF7 for USART2 in alternate function registers
GPIOA->AFR[0] |= 0x7700;
}
Se inicializan las GPIO, el puerto A, B y C por esto el valor del reloj es:
RCC->AHB2ENR |= 0x00000007
30 de junio de 2020
9
Se definen los pines de salida para los leds que simulan el semáforo.
Para esto primero se limpian los puertos y luego si se definen como salida. En la
imagen 3 se muestra como encontrar el valor para definir los pines 5 y 7 como
salida del puerto A, GPIOA->MODER |= 0x00004400
Esto se hace con el registro MODER quien es quien me define el modo en el que
va a trabajar el pin.
30 de junio de 2020
10
figura3
Del mismo modo se hace para el puerto B y C. A demás de esto debe definirse el
Pin 13 del puerto C como USER BOTON porque allí es donde está el botón del
usuario.
Figura4
30 de junio de 2020
11
característica especial, este registro permite configurar la velocidad a la que van a
trabajar los pines y para este problema será una velocidad alta:
GPIOA->OSPEEDR |= 0x000000A0
Y por ultimo se modifica el registro AFRL la que permite definir la función alterna.
Este se utiliza para los puertos desde le 0 hasta el 7.
GPIOA->AFR[0] |= 0x7700
30 de junio de 2020
12
5. Ext_init()
30 de junio de 2020
13
RCC->APB2ENR |= 0x1;
/*
* Para configurar los registros de las interrupciones section 14.5
* se debe configurar el registro IMR1 -> enmascarar el pin por
donde se hace la interrupcion
* se debe configurar la forma en que se va a detectar la
interrupcion, si es por flanco de subida RTSR o bajada FTSR
* se debe configurar la prioridad de la interrupcion NVIC-> IP
* por ultimo se debe habilitar la interrupcion
* EXTI15_10_IRQn es el manejador que se encarga de solicitar la
interrupcion, como se va a utilizar el boton, este esta
* asociado a EXTI13, se usa EXTI15_10 porque este comprende las
interrupciones desde la 10 hasta la 15,
* pero es necesario especificar que se va a utilizar la 13. EXTICR
*/
// Writing a 0b0010 to pin13 location ties PC13 to EXT4
SYSCFG->EXTICR[3] |= 0x20; // Write 0002 to map PC13 to EXTI4
// Choose either rising edge trigger (RTSR1) or falling edge
trigger (FTSR1)
EXTI->FTSR1 |= 0x2000; // Enable rising edge trigger on EXTI4
// Mask the used external interrupt numbers.
EXTI->IMR1 |= 0x2000; // Mask EXTI4
// Set Priority for each interrupt request
NVIC->IP[EXTI15_10_IRQn] = 0x10; // Priority level 1
// enable EXT0 IRQ from NVIC
NVIC_EnableIRQ(EXTI15_10_IRQn);
}
6. TIMER_init()
30 de junio de 2020
14
* de encendido y apagado.
*/
void TIMER_init(void){
/*
* Para configurar los registros necesarios section 31.4.
* Primero se debe configurar el registro que habilita el reloj que
permite usar el TIMER.section 6.4.19
* se debe configurar el preescalor para establecer la frecuencia
de conteo del timmer, para esto se configura el registro PSC.
* se debe configurar el valor hasta el cual el timer va a contar
para generar la base de tiempo, en este caso (segun el doc del
* ejercicio) cada segundo, para esto se configura el registro ARR.
* se debe configurar el registro DIER en el bit 0 para que cada
vez que el timmer cuente hasta la base de tiempo,
* se genere una interrupcion para lo cual se debe poner un 1 el
el bit 0 del registro.
* por ultimo establecer una prioridad para la interrupcion del
timmer usando el registro NVIC
* NVIC -> NESTED VECTOR INTERRUP CONTROL
* por ultimo se debe habilitar el contador del Timer a traves del
registro CR1.
*/
// enable TIM2 clock (bit0)
RCC->APB1ENR1 |= (1<<0);
TIM2->PSC = 7999;
TIM2->ARR = 400;
// Update Interrupt Enable
TIM2->DIER |= (1 << 0);
NVIC_SetPriority(TIM2_IRQn, 2); // Priority level 2
// enable TIM2 IRQ from NVIC
NVIC_EnableIRQ(TIM2_IRQn);
// Enable Timer 2 module (CEN, bit0)
TIM2->CR1 |= (1 << 0);
// Decirle al TIMER que comience a contar
}
4 x 10 6
ARR= =500 Hz
8000
30 de junio de 2020
15
TIM2->ARR = 500
7. UART_init
30 de junio de 2020
16
/*
* formula para calcular el Baudrate
* TX/RX BR = Fclk/(USARTDIV)
* 4MHz internal clock by default
* TX/RX BR = 4000000/9600=416.16
* 416.16d = 01A0hex
*/
USART2->BRR |= 0x01A0;
// Enable USART2 UE, bit 0
USART2->CR1 |= (1 << 0);
}
/*
30 de junio de 2020
17
Se configuran los registros:
CR1 longitud de la palabra, se ponen los bits 28 y 12 en 0, se define la
longitud con 8 bits de parada. También se puede configurar el bit 10 que es
el bit de paridad, pero como no es común usarlo se deja deshabilitado.
Para habilitar tanto e transmisor como el receptor de la USART, el bit 3
como transmisor y el bit 2 como receptor, ambos se deben poner en 1.
30 de junio de 2020
18
CR2 en este registro se define el numero de bit de parada
30 de junio de 2020
19
BRR registro para determinar la velocidad a la cual se van a transmitir los
datos
Fclk
BR=
USARTDIV
Fclk=frecuencia del reloj=4MHZ
USARTDIV es el Bautrade deseado, para este caso=9600
4000000
BR=
9600
BR=416,67
416 en hexadecimal = 1A0
USART2->BRR |= 0x01A0
Por ultimo se habilita el UART para que comience a transmitir
8. State Machine
La Máquina de estados está diseñada para iterar en esta secuencia, tal y como se
describe en la guía.
30 de junio de 2020
20
void semaforo(void){
enum states {STATE0, STATE1, STATE2, STATE3,STATE4} current_state;
int lock=0;
current_state = STATE0; //set the initial state
while(1){
switch(current_state){
case STATE0:
for (uint32_t i=0; i<sizeof(mensaje); i++){
// send character
USART2->TDR = mensaje[i];
// wait for transmit complete
while(!(USART2->ISR & (1 << 6)));
// slow down
for(int i=0; i<1000000; i++);
}
current_state = STATE1;
break;
case STATE1:
if (lock==0){
t=con;
lock=1;
//semaforo vehicular
GPIOA->ODR |= (1 << 5); //Red ON
GPIOB->ODR &= (0 << 5); //Amber OFF
GPIOC->ODR &= (0 << 7); //Green OFF
//semaforo peatonal
GPIOA->ODR &= (0 << 7); //Red OFF
GPIOB->ODR |= (1 << 6); //Green ON
}
if(con>=(t+10)){
current_state = STATE2;
lock=0;
}else{
current_state = STATE1;
}
break;
case STATE2:
if (lock==0){
t=con;
lock=1;
//semaforo vehicular
GPIOA->ODR |= (1 << 5); //Red ON
GPIOB->ODR |= (1 << 5); //Amber ON
GPIOC->ODR &= (0 << 7); //Green OFF
//semaforo peatonal
GPIOA->ODR |= (1 << 7); //Red ON
GPIOB->ODR &= (0 << 6); //Green OFF
30 de junio de 2020
21
}
if(con>=(t+2)){
current_state = STATE3;
lock=0;
}else{
current_state = STATE2;
}
break;
case STATE3:
if (lock==0){
boton=1;
t=con;
lock=1;
//semaforo vehicular
GPIOA->ODR &= (0 << 5); //Red ON
GPIOB->ODR &= (0 << 5); //Amber OFF
GPIOC->ODR |= (1 << 7); //Green OFF
//semaforo peatonal
GPIOA->ODR |= (1 << 7); //Red ON
GPIOB->ODR &= (0 << 6); //Green ON
}
if(con>=(t+14)){
current_state = STATE4;
lock=0;
}else if(boton==0){
current_state = STATE1;
boton=1;
lock=0;
}else{
current_state = STATE3;
}
break;
case STATE4:
if (lock==0){
t=con;
lock=1;
//semaforo vehicular
GPIOA->ODR &= (0 << 5); //Red ON
GPIOB->ODR |= (1 << 5); //Amber OFF
GPIOC->ODR &= (0 << 7); //Green OFF
//semaforo peatonal
GPIOA->ODR |= (1 << 7); //Red ON
GPIOB->ODR &= (0 << 6); //Green OFF
}
if(con>=(t+3)){
current_state = STATE0;
lock=0;
}else{
30 de junio de 2020
22
current_state = STATE4;
}
break;
}// switch(current_state)
} //while(true)
}
Se definieron 5 estados donde el estado cero es donde se hace la transmisión por
uart de la secuencia de los leds de los semáforos vehicular y peatonal.
Enum es una estructura creada para definir los estados llamada
current_state
Lock seguro
TDR registro para transmitir
ISR registro que indica el estado en el que esta la transmisión, por esto el
bit 6 estara en 1 cuando la transmisión se haya completado y en 0 cuando
no
30 de junio de 2020
23
Aclaraciones:
30 de junio de 2020
24
2) Las siglas que aparecen en pantalla hacer referencia a:
Referencias:
30 de junio de 2020
25
RM0351 Reference manual, STM32L4x5 and STM32L4x6 advanced
Arm-based 32-bit MCUs.
https://www.st.com/content/ccc/resource/technical/document/reference_
manual/
02/35/09/0c/4f/f7/40/03/DM00083560.pdf/files/DM00083560.pdf/jcr:conte
nt/translations/ en.DM00083560.pdf
STM32l476rg datasheet.
https://www.st.com/resource/en/datasheet/stm32l476rg.pdf
30 de junio de 2020
26