#include "stm32f4xx.h" #include "stm32f4xx_rcc.h" #include "stm32f4xx_gpio.h" #include "stm32f4xx_usart.h" #include "misc.h" #include#include // easy to remember names for Pins 12, 13, 14 #define RedLED 0x1000 #define GreenLED 0x2000 #define BlueLED 0x4000 // create initialization structures USART_InitTypeDef USART_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; USART_ClockInitTypeDef USART_ClockInitStructure; NVIC_InitTypeDef NVIC_InitStructure; // define RGB color type typedef struct { uint8_t R, G, B; } ColorTypeDef; ColorTypeDef ColorStructure; // create color type instance uint32_t ISRCount = 0; // counts interrupt service routines uint32_t total = 0; // total duration of one PWM cycle uint32_t color = 0x000000; // storage for color value // function prototypes void AssignColor(ColorTypeDef * ColorStructure, uint32_t TargetColor); void ColorPWM(ColorTypeDef * ColorStructure); void InitializePeriph(); uint8_t ascii_to_hex(uint8_t ascii); int main(void) { InitializePeriph(); while(!USART_GetFlagStatus(USART3, USART_FLAG_TXE)){} // wait for empty transmit buffer printf("RGB LED Control with HTML Color Codes!"); while(!USART_GetFlagStatus(USART3, USART_FLAG_TXE)){} // wait for empty transmit buffer while (1) {ColorPWM(&ColorStructure);} // constantly repeats PWM cycle } /* InitializePeriph() prepares all of the STM32's peripherals for this project * Required peripherals are GPIO and USART * NVIC assigns an interrupt service routine to an incoming USART message */ void InitializePeriph(){ RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); // Set GPIO pins Alt. Function to USART1 GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_USART3); GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_USART3); // PC10: USART TX, PC11: USART RX GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 + GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_Init(GPIOC, &GPIO_InitStructure); // PD12, PD13, PD14: Outputs for R, G, B GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 + GPIO_Pin_13 + GPIO_Pin_14; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_Init(GPIOD, &GPIO_InitStructure); // Initialize USART USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_Init(USART3, &USART_InitStructure); USART_Cmd(USART3,ENABLE); // Assign NVIC to USART3 NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_Init(&NVIC_InitStructure); USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); } /* Incoming UART messages will trigger an interrupt. The ISR keeps track of * the incoming color code and updates the color structure as it receives * characters. */ void USART3_IRQHandler(void) { uint8_t hex = 0; if (USART_GetITStatus(USART3, USART_IT_RXNE) != RESET){ hex = ascii_to_hex((char)USART_ReceiveData(USART3)); } if (ISRCount % 6 == 0) color = 0; color += hex << 4*(5 - (ISRCount % 6)); ISRCount++; AssignColor(&ColorStructure, color); } /* ascii_tohex() takes an ascii character and translates it * to the corresponding hexadecimal value */ uint8_t ascii_to_hex(uint8_t ascii){ uint8_t hex = 0; switch (tolower(ascii)){ case 'f': hex = 0xf; break; case 'e': hex = 0xe; break; case 'd': hex = 0xd; break; case 'c': hex = 0xc; break; case 'b': hex = 0xb; break; case 'a': hex = 0xa; break; case '9': hex = 0x9; break; case '8': hex = 0x8; break; case '7': hex = 0x7; break; case '6': hex = 0x6; break; case '5': hex = 0x5; break; case '4': hex = 0x4; break; case '3': hex = 0x3; break; case '2': hex = 0x2; break; case '1': hex = 0x1; break; case '0': hex = 0x0; break; default: hex = 0x0; break; } return hex; } /* AssignColor() takes a html color code and parses it into * Red, Green and Blue values */ void AssignColor(ColorTypeDef * ColorStructure, uint32_t TargetColor){ ColorStructure->R = (TargetColor&0x00FF0000)/0x10000; ColorStructure->G = (TargetColor&0x0000FF00)/ 0x100; ColorStructure->B = (TargetColor&0x000000FF)/0x1; } /* ColorPWM applies the RGB values to PWM pulse widths and apply * the appropriate signals to the GPIO */ void ColorPWM(ColorTypeDef * ColorStructure){ uint16_t rLimit = (ColorStructure->R + ColorStructure->G + ColorStructure->B); uint16_t gLimit = (ColorStructure->G + ColorStructure->B); uint8_t bLimit = (ColorStructure->B); uint8_t r, g, b; for (uint16_t scan = 0; scan <= 0x0300; scan++){ if (scan < rLimit && scan >= gLimit && scan >= bLimit){ g = 0; b = 0; r = 1; } else if (scan < gLimit && scan >= bLimit){ b = 0; r = 0; g = 1; } else if (scan < bLimit){ r = 0; g = 0; b = 1; } else if (rLimit == 0){ r = 0; g = 0; b = 0; } else { r = 0; g = 0; b = 0; } GPIO_Write(GPIOD, (RedLED*r) | (GreenLED*g) | (BlueLED*b)); } }