基于STM32F103系列微控制器使用按键/LED/UART实现抢答器实验代码
时间: 2023-11-27 15:04:33 浏览: 31
以下是基于STM32F103系列微控制器使用按键/LED/UART实现抢答器的示例代码,供参考:
```
#include "stm32f10x.h"
#include "stdio.h"
#define LED1_PIN GPIO_Pin_12 // LED1引脚
#define LED2_PIN GPIO_Pin_13 // LED2引脚
#define BUTTON_PIN GPIO_Pin_0 // 按键引脚
#define UART_TX_PIN GPIO_Pin_9 // UART输出引脚
#define UART_BAUDRATE 9600 // UART波特率
#define TIMER_INTERVAL 32768 // 定时器计数器值
#define TIMER_DELAY 10 // 抢答持续时间(秒)
volatile unsigned int timer_count = 0; // 定时器计数器
volatile unsigned int button_pressed = 0; // 按键是否被按下
volatile unsigned int button_released = 0; // 按键是否被释放
volatile unsigned int button_acknowledged = 0; // 按键是否被确认
void uart_init()
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE); // 启用GPIOA和USART1时钟
GPIO_InitStructure.GPIO_Pin = UART_TX_PIN; // UART输出引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = UART_BAUDRATE; // 设置波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 设置字长
USART_InitStructure.USART_StopBits = USART_StopBits_1; // 设置停止位
USART_InitStructure.USART_Parity = USART_Parity_No; // 设置校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx; // 设置UART为发送模式
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE); // 启用USART1
}
void uart_send(char *data)
{
while (*data) // 循环发送数据
{
while (!(USART1->SR & USART_SR_TXE)); // 等待UART发送缓冲器就绪
USART1->DR = *data++; // 发送数据
}
}
void led_init()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 启用GPIOB时钟
GPIO_InitStructure.GPIO_Pin = LED1_PIN | LED2_PIN; // LED引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_ResetBits(GPIOB, LED1_PIN | LED2_PIN); // 关闭LED
}
void button_init()
{
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 启用GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); // 启用AFIO时钟
GPIO_InitStructure.GPIO_Pin = BUTTON_PIN; // 按键引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0); // 设置中断线路
EXTI_InitStructure.EXTI_Line = EXTI_Line0; // EXTI线路
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; // 下降沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; // NVIC中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void timer_init()
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // 启用TIM2时钟
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
TIM_TimeBaseStructure.TIM_Period = TIMER_INTERVAL - 1; // 设置计数器周期
TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1; // 设置预分频器
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); // 启用TIM2更新中断
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; // NVIC中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM2, ENABLE); // 启动TIM2计数器
}
void EXTI0_IRQHandler() // 按键中断函数
{
if (GPIO_ReadInputDataBit(GPIOA, BUTTON_PIN) == RESET) // 如果按键被按下
{
button_pressed = 1; // 设置按键已被按下标志
EXTI_ClearITPendingBit(EXTI_Line0); // 清除中断标志位
}
else // 如果按键被释放
{
button_released = 1; // 设置按键已被释放标志
}
}
void TIM2_IRQHandler() // 计时器中断函数
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) // 如果计时器溢出
{
timer_count++; // 计数器自增
if (timer_count >= TIMER_DELAY) // 如果抢答时间到
{
if (button_pressed) // 如果有人抢答成功
{
GPIO_SetBits(GPIOB, LED1_PIN); // 打开LED1
uart_send("success"); // 发送抢答成功信息
}
else // 如果没有人抢答成功
{
GPIO_SetBits(GPIOB, LED2_PIN); // 打开LED2
uart_send("fail"); // 发送抢答失败信息
}
button_acknowledged = 1; // 设置按键已被确认标志
timer_count = 0; // 重置计数器
}
TIM_ClearITPendingBit(TIM2, TIM_IT_Update); // 清除计时器中断标志位
}
}
int main()
{
uart_init(); // 初始化UART
led_init(); // 初始化LED
button_init(); // 初始化按键
timer_init(); // 初始化计时器
while (1)
{
if (button_acknowledged) // 如果按键已被确认
{
button_pressed = 0; // 重置按键状态
button_released = 0;
button_acknowledged = 0;
GPIO_ResetBits(GPIOB, LED1_PIN | LED2_PIN); // 关闭LED
delay_ms(100); // 延迟一段时间,避免按键抖动
}
}
}
```
在上述代码中,我们使用了STM32F103系列微控制器实现了抢答器功能。其中,使用了按键中断、定时器中断、LED输出和UART通信功能。通过这些功能的组合,我们可以实现一个简单的抢答器,用于课堂或会议等场合。