Embedded systems
EECE 237 S15 - Lab 4. (XC).pdf
EECE 237 Spring 2015 Homework Assignment #4 – Display scrolling, button press detection (Extra Credit) Assignment: Starting with the template file (on the BbLearn page), create a program that uses the supplied LCD_scroll() function to scroll a text message on the LCD display both left and right. A single button press should cause the display to scroll one position. A double press (two button presses with 1 second) should cause the direction of the scrolling to change. The first press will move the display one position to the right, and every single press after that will continue to move it to the right. When a double press occurs, the direction of the text shift changes, so every single press after that will shift the text that direction. The LED circle should also move a single lit LED clockwise each time the display is shifted right, and counter-clockwise each time the display is shifted left.
• Use the LCD_scroll() function to shift the display left or right (do not rewrite it each time) • The display should be shifting right at the start of execution • Use the constants defined for the RIGHT and LEFT direction settings (to call LCD_scroll() ) • Use the defined PRESS_TIME constant to define the maximum number of ticks between the
two button presses for a double press (do not change the value) • Do not worry about the display scrolling off the screen (if you keep scrolling in the same
direction for about 10 steps, it will wrap back onto the screen) • The time measurement should be based on SysTickInterrupts. • All delays should be based on this Timer (No count delay loops) • The button press must be interrupt based (not polled)
Deliverables:
1) Source code for solution program: C source file - submitted via BbLearn page. (Do not submit other project files). The file MUST be named as follows:
<first initial>_<last name>_hw4.c for example, mine would be d_word_hw4.c
The source code file must contain your name and student ID in the header block at the top of the page, and should be commented enough to be easy to read
Due Date: Friday, May 15th – Assignment must be submitted to BbLearn by 8pm.
__MACOSX/._EECE 237 S15 - Lab 4. (XC).pdf
EECE 237 S15 Lab4 Template.c
// // EECE 237 S15 // Lab 4 (XC) template // //includes for the project #include "stm32F30x.h" #include "STM32f3_discovery.h" #include "stm32f30x_gpio.h" #include "stm32f30x_i2c.h" #include "stm32f3_discovery_lsm303dlhc.h" #include "stm32f3_discovery_l3gd20.h" #include "main.h" #include "stdio.h" #include "string.h" // Constants ----------------------------------- #define SYSTICK_MASK 0xF000 #define TIM3_MASK 0x0F00 #define RIGHT 0 #define LEFT 1 RCC_ClocksTypeDef RCC_Clocks; GPIO_InitTypeDef GPIO_InitStructure; void IO_Init(void); void I2C_init(void); void I2C2_init(void); void Timer3_Init(void); unsigned int TIM3_tick_count = 0; unsigned int tick_count = 0; volatile int ButtonPressed = 0; void LCD_write(int,int, char); void LCD_clear(void); void LCD_contrast(int); // Contrast level = 1..50 void LCD_backlight(int); // Backlight level = 1..8 void LCD_scroll (int); // Scroll 1 space RIGHT or LEFT void Delay(uint32_t nTime); static __IO uint32_t TimingDelay; char message[16]; char ready_msg[] = " Ready...."; int main(void) { int i; IO_Init(); Timer3_Init(); I2C2_init(); while(I2C_GetFlagStatus(I2C2, I2C_ISR_BUSY) != RESET); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LCD_contrast(40); LCD_backlight(6); LCD_clear(); for (i=0; i < 10; i++) LCD_write(0, i, ready_msg[i]); // Write "Ready..." tick_count = 0; while (!ButtonPressed); ButtonPressed = 0; GPIOE->ODR = 0; while(1){ sprintf(message, "Ticks = %5i", tick_count); for (i=0; i < strlen(message); i++) LCD_write(0, i, message[i]); // Display number on 1st line of display tick_count = 0; while (!ButtonPressed); ButtonPressed = 0; //GPIOE->ODR = (((++j%8)< 7) ? (0x0200 << (j%8)) : (0x0200 >> (8 - (j%8)))); LCD_clear(); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void IO_Init() { EXTI_InitTypeDef EXTI_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; /* SysTick end of count event each 1ms */ RCC_GetClocksFreq(&RCC_Clocks); SysTick_Config(RCC_Clocks.HCLK_Frequency / 1000); /* GPIOE Periph clock enable */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOE, ENABLE); /* Configure PE14 and PE15 in output pushpull mode */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15 | GPIO_Pin_14 | GPIO_Pin_13 | GPIO_Pin_12 | GPIO_Pin_11| GPIO_Pin_10| GPIO_Pin_9| GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //GPIO_PuPd_NOPULL GPIO_Init(GPIOE, &GPIO_InitStructure); /* GPIOA Periph clock enable */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); /* Configure PA0 in input mode */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Configure PA8 in output mode */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_7); // TIM1_CH1 -> Pin A8 /* Enable GPIOA clock */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); /* Configure PA0 pin as input floating */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Enable SYSCFG clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); /* Connect EXTI0 Line to PA0 pin */ SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0); /* Configure EXTI0 line */ EXTI_InitStructure.EXTI_Line = EXTI_Line0; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); /* Enable and set EXTI0 Interrupt to the lowest priority */ NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } void I2C2_init(void) { GPIO_InitTypeDef GPIO_InitStructure; I2C_InitTypeDef I2C_InitStructure; RCC_I2CCLKConfig(RCC_I2C2CLK_SYSCLK); RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_4); GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_4); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_Init(GPIOA, &GPIO_InitStructure); I2C_DeInit(I2C2); I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable; I2C_InitStructure.I2C_DigitalFilter = 0x00; I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_InitStructure.I2C_Timing = 0xC062121F; I2C_Init(I2C2, &I2C_InitStructure); I2C_Cmd(I2C2, ENABLE); } // // Scroll LCD Display - Direction should be LEFT or RIGHT // void LCD_scroll(int direction) { I2C_TransferHandling(I2C2, 0x50 , 3, I2C_SoftEnd_Mode, I2C_Generate_Start_Write); while(I2C_GetFlagStatus(I2C2, I2C_ISR_TXIS) == RESET); I2C_SendData(I2C2, 0xFE); while(I2C_GetFlagStatus(I2C2, I2C_ISR_TXIS) == RESET); if (direction == LEFT) I2C_SendData(I2C2, 0x55); else I2C_SendData(I2C2, 0x56); while(I2C_GetFlagStatus(I2C2, I2C_ISR_TXIS) == RESET); Delay(20); } void LCD_write(int row, int col, char data) { // Move to sepcified row, col //while(I2C_GetFlagStatus(I2C2, I2C_ISR_BUSY) != RESET); I2C_TransferHandling(I2C2, 0x50 , 3, I2C_SoftEnd_Mode, I2C_Generate_Start_Write); while(I2C_GetFlagStatus(I2C2, I2C_ISR_TXIS) == RESET); I2C_SendData(I2C2, 0xFE); while(I2C_GetFlagStatus(I2C2, I2C_ISR_TXIS) == RESET); I2C_SendData(I2C2, 0x45); while(I2C_GetFlagStatus(I2C2, I2C_ISR_TXIS) == RESET); if (!row) // if row == 0 I2C_SendData(I2C2, col); else // else row asumed to be 1 I2C_SendData(I2C2, (0x40 + col)); I2C_TransferHandling(I2C2, 0x50 , 1, I2C_SoftEnd_Mode, I2C_Generate_Start_Write); while(I2C_GetFlagStatus(I2C2, I2C_ISR_TXIS) == RESET); I2C_SendData(I2C2, data); } // // Set LCD Contrast - Level should be 1..50 (Seems to work best if > 35) // void LCD_contrast(int level) { //while(I2C_GetFlagStatus(I2C2, I2C_ISR_BUSY) != RESET); I2C_TransferHandling(I2C2, 0x50 , 3, I2C_SoftEnd_Mode, I2C_Generate_Start_Write); while(I2C_GetFlagStatus(I2C2, I2C_ISR_TXIS) == RESET); I2C_SendData(I2C2, 0xFE); while(I2C_GetFlagStatus(I2C2, I2C_ISR_TXIS) == RESET); I2C_SendData(I2C2, 0x52); while(I2C_GetFlagStatus(I2C2, I2C_ISR_TXIS) == RESET); I2C_SendData(I2C2, level); Delay(20); } // // Set LCD Backlight - Level should be 1..8 (Seems to work best if > 1) // void LCD_backlight(int level) { //while(I2C_GetFlagStatus(I2C2, I2C_ISR_BUSY) != RESET); I2C_TransferHandling(I2C2, 0x50 , 3, I2C_SoftEnd_Mode, I2C_Generate_Start_Write); while(I2C_GetFlagStatus(I2C2, I2C_ISR_TXIS) == RESET); I2C_SendData(I2C2, 0xFE); while(I2C_GetFlagStatus(I2C2, I2C_ISR_TXIS) == RESET); I2C_SendData(I2C2, 0x53); while(I2C_GetFlagStatus(I2C2, I2C_ISR_TXIS) == RESET); I2C_SendData(I2C2, level); Delay(20); } void LCD_clear() { //while(I2C_GetFlagStatus(I2C2, I2C_ISR_BUSY) != RESET); I2C_TransferHandling(I2C2, 0x50 , 2, I2C_SoftEnd_Mode, I2C_Generate_Start_Write); while(I2C_GetFlagStatus(I2C2, I2C_ISR_TXIS) == RESET); I2C_SendData(I2C2, 0xFE); while(I2C_GetFlagStatus(I2C2, I2C_ISR_TXIS) == RESET); I2C_SendData(I2C2, 0x51); Delay(20); } void Timer3_Init(void) { NVIC_InitTypeDef NVIC_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; /* TIM3 clock enable */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); TIM_TimeBaseStructure.TIM_Period = 50000; TIM_TimeBaseStructure.TIM_Prescaler = (SystemCoreClock/1000000)-1; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM7, &TIM_TimeBaseStructure); /* Enable the TIM3 gloabal Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); TIM_ARRPreloadConfig(TIM3, ENABLE); /* TIM3 enable counter */ TIM_Cmd(TIM3, ENABLE); TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); } // // Timer 3 Interrupt Handler // void TIM3_IRQHandler(void) { TIM3_tick_count++; if (!(TIM3_tick_count % 200)) GPIOE->ODR ^= TIM3_MASK; TIM_ClearITPendingBit(TIM3, TIM_IT_Update); } /** * @brief Inserts a delay time. * @param nTime: specifies the delay time length, in milliseconds. * @retval None */ void Delay(uint32_t nTime) { TimingDelay = nTime; while(TimingDelay != 0); } /** * @brief Decrements the TimingDelay variable. * @param None * @retval None */ void TimingDelay_Decrement(void) { if (TimingDelay != 0x00) { TimingDelay--; } } void SysTick_Handler(void) { TimingDelay_Decrement(); tick_count++; if (!(tick_count % 200)) GPIOE->ODR ^= SYSTICK_MASK; } void EXTI0_IRQHandler(void) { if (EXTI_GetITStatus(USER_BUTTON_EXTI_LINE) == SET) { ButtonPressed = 1; /* Clear the EXTI line 0 pending bit */ EXTI_ClearITPendingBit(USER_BUTTON_EXTI_LINE); } }