Created
August 13, 2024 10:07
-
-
Save tsl0922/90e11c3b4b2b202de253e754d1efd5ae to your computer and use it in GitHub Desktop.
stm32 RGB led and buzzer demo (R/G/B: PA0/PA1/PA2, Buzzer: PA6).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "stm32f10x.h" | |
void Delay_us(uint32_t xus) { | |
SysTick->LOAD = 72 * xus; | |
SysTick->VAL = 0x00; | |
SysTick->CTRL = 0x00000005; | |
while(!(SysTick->CTRL & 0x00010000)); | |
SysTick->CTRL = 0x00000004; | |
} | |
void Delay_ms(uint32_t xms) { | |
while(xms--) Delay_us(1000); | |
} | |
void Buzzer_GPIO_Config(void) { | |
// Enable GPIOA clock | |
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); | |
GPIO_InitTypeDef GPIO_InitStructure; | |
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; // Assuming PA6 for TIM3 Channel 1 | |
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; | |
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; | |
GPIO_Init(GPIOA, &GPIO_InitStructure); | |
} | |
void Buzzer_PWM_Config(void) { | |
// Enable TIM3 clock | |
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); | |
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; | |
TIM_OCInitTypeDef TIM_OCInitStructure; | |
// Time base configuration | |
TIM_TimeBaseStructure.TIM_Period = 999; // 1kHz frequency | |
TIM_TimeBaseStructure.TIM_Prescaler = 71; // 1MHz timer clock | |
TIM_TimeBaseStructure.TIM_ClockDivision = 0; | |
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; | |
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); | |
// PWM1 Mode configuration: Channel 1 | |
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; | |
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; | |
TIM_OCInitStructure.TIM_Pulse = 500; // 50% duty cycle | |
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; | |
TIM_OC1Init(TIM3, &TIM_OCInitStructure); | |
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); | |
// Enable TIM3 counter | |
TIM_Cmd(TIM3, ENABLE); | |
} | |
void Buzzer_SetFreq(uint16_t freq) { | |
// Calculate the period value based on the desired frequency | |
uint16_t period = 1000000 / freq; | |
// Update the period value of TIM3 | |
TIM3->ARR = period; | |
} | |
void Buzzer_SetDuty(uint16_t duty) { | |
// Calculate the pulse value based on the desired duty cycle | |
uint16_t pulse = (duty * (TIM3->ARR + 1)) / 100; | |
// Update the pulse value of TIM3 | |
TIM3->CCR1 = pulse; | |
} | |
void RGB_GPIO_Config(void) { | |
// Enable GPIO clock | |
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); | |
GPIO_InitTypeDef GPIO_InitStructure; | |
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2; // Assuming PA0, PA1, PA2 for RGB | |
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; | |
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; | |
GPIO_Init(GPIOA, &GPIO_InitStructure); | |
} | |
void RGB_PWM_Config(void) { | |
// Enable TIM2 clock | |
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); | |
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; | |
TIM_OCInitTypeDef TIM_OCInitStructure; | |
// Time base configuration | |
TIM_TimeBaseStructure.TIM_Period = 255; // 8-bit resolution | |
TIM_TimeBaseStructure.TIM_Prescaler = 0; | |
TIM_TimeBaseStructure.TIM_ClockDivision = 0; | |
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; | |
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); | |
// PWM1 Mode configuration: Channel 1 | |
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; | |
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; | |
TIM_OCInitStructure.TIM_Pulse = 0; | |
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; | |
TIM_OC1Init(TIM2, &TIM_OCInitStructure); | |
TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable); | |
// PWM1 Mode configuration: Channel 2 | |
TIM_OC2Init(TIM2, &TIM_OCInitStructure); | |
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable); | |
// PWM1 Mode configuration: Channel 3 | |
TIM_OC3Init(TIM2, &TIM_OCInitStructure); | |
TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable); | |
// Enable TIM2 counter | |
TIM_Cmd(TIM2, ENABLE); | |
} | |
void RGB_Set(uint8_t red, uint8_t green, uint8_t blue) { | |
TIM_SetCompare1(TIM2, red); // Set duty cycle for Red | |
TIM_SetCompare2(TIM2, green); // Set duty cycle for Green | |
TIM_SetCompare3(TIM2, blue); // Set duty cycle for Blue | |
} | |
void RGB_Get_Gradient_Color(uint32_t step, uint8_t *red, uint8_t *green, uint8_t *blue) { | |
uint8_t phase = (step / 256) % 3; | |
uint8_t value = step % 256; | |
switch (phase) { | |
case 0: | |
*red = 255 - value; | |
*green = value; | |
*blue = 0; | |
break; | |
case 1: | |
*red = 0; | |
*green = 255 - value; | |
*blue = value; | |
break; | |
case 2: | |
*red = value; | |
*green = 0; | |
*blue = 255 - value; | |
break; | |
} | |
} | |
// cycle the rgb color smoothly | |
void RGB_Play(uint16_t delay, uint16_t count) { | |
static uint32_t step = 0; | |
uint8_t red, green, blue; | |
for (int i = 0; i < count; i++) { | |
RGB_Get_Gradient_Color(step, &red, &green, &blue); | |
RGB_Set(red, green, blue); | |
step++; | |
Delay_ms(delay); | |
} | |
} | |
// Twinkle Twinkle Little Star | |
void Buzzer_Play() { | |
uint16_t tones[] = {0, 262, 294, 330, 349, 392, 440, 494}; | |
char *melody = "1155665-4433221-5544332-5544332-1155665-4433221"; | |
uint32_t step = 0; | |
uint8_t red, green, blue; | |
uint16_t i = 0; | |
while (melody[i] != '\0') { | |
if (melody[i] == '0' || melody[i] == '-') { | |
Buzzer_SetDuty(0); | |
} else { | |
Buzzer_SetFreq(tones[melody[i] - '0']); | |
Buzzer_SetDuty(50); | |
} | |
RGB_Play(4, 100); | |
Buzzer_SetDuty(0); | |
RGB_Play(4, 25); | |
i++; | |
} | |
} | |
int main(void) { | |
RGB_GPIO_Config(); | |
RGB_PWM_Config(); | |
Buzzer_GPIO_Config(); | |
Buzzer_PWM_Config(); | |
while (1) { | |
Buzzer_Play(); | |
Delay_ms(500); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment