使用TIM3设计一个时间基准,通过USART1每3秒发送一次字符串"HELLO"。该怎么写?
#include "stm32f1xx.h"
void TIM3_IRQHandler(void)
{
if (TIM3->SR & TIM_SR_UIF)
{
TIM3->SR &= ~TIM_SR_UIF; // 清除更新事件标志位
USART1->DR = 'H'; // 发送字符'H'
}
}
void USART1_IRQHandler(void)
{
if (USART1->SR & USART_SR_TXE)
{
USART1->DR = 'E'; // 发送字符'E'
}
}
int main(void)
{
// 启用相应外设的时钟,配置引脚等
// 配置TIM3定时器
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; // 启用TIM3时钟
TIM3->PSC = 7199; // 设置预分频器,72MHz / (7199 + 1) = 10kHz
TIM3->ARR = 29999; // 设置自动重载寄存器,10kHz * 3s = 30000个时钟周期
TIM3->DIER |= TIM_DIER_UIE; // 启用更新事件中断
NVIC_EnableIRQ(TIM3_IRQn); // 使能TIM3中断
// 配置USART1串口
RCC->APB2ENR |= RCC_APB2ENR_USART1EN; // 启用USART1时钟
USART1->BRR = 72000000 / 9600; // 设置波特率为9600
USART1->CR1 |= USART_CR1_TE; // 使能发送
USART1->CR1 |= USART_CR1_TXEIE; // 启用发送中断
NVIC_EnableIRQ(USART1_IRQn); // 使能USART1中断
// 启动定时器
TIM3->CR1 |= TIM_CR1_CEN;
while (1)
{
// 主循环中可以执行其他操作
}
}
首先需要对TIM3模块进行配置,以每3秒触发一次中断。具体步骤如下:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
TIM_TimeBaseStructure.TIM_Prescaler = 72-1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_Period = 9000-1; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
其中,预分频器和计数值的设置需要结合主频和需要的计数时间进行计算。
NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM3, ENABLE);
void TIM3_IRQHandler(void)
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
char * hello = "HELLO\n";
while(hello)
{
USART_SendData(USART1, hello);
hello++;
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}
}
}
其中,使用了USART1发送数据,根据题目要求需要设置波特率为115200,1位停止位,无校验位。USART1的配置也需要在代码中实现,具体步骤如下:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
USART_InitStructure.USART_BaudRate = 115200; 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_Rx | USART_Mode_Tx; USART_Init(USART1, &USART_InitStructure); USART_Cmd(USART1, ENABLE);
char * start = "Start\n";
while(start)
{
USART_SendData(USART1, start);
start++;
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}
完整代码如下:
USART_InitTypeDef USART_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); // 串口时钟使能 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); // 定时器时钟使能
USART_InitStructure.USART_BaudRate = 115200; // 波特率为115200
USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 数据位8位
USART_InitStructure.USART_StopBits = USART_StopBits_1; // 停止位1位
USART_InitStructure.USART_Parity = USART_Parity_No; // 无校验
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 无硬件流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 置位RX和TX模式
USART_Init(USART1, &USART_InitStructure); // 初始化串口1
USART_Cmd(USART1, ENABLE); // 开启串口1
TIM_TimeBaseStructure.TIM_Prescaler = 7200-1; // 预分频器为72,计数1秒,需要设置1000ms/1440=0.694ms计数一次
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // TIM向上计数模式
TIM_TimeBaseStructure.TIM_Period = 2083-1; // 计数2083次,即3秒
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; // 时钟分割1
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; // 重复计数器
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); // 初始化TIM3
// 定时器中断优先级0
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM3, ENABLE); // 开启计数器
char * start = "Start\n";
while(*start)
{
USART_SendData(USART1, *start);
start++;
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}
while(1);
}
void TIM3_IRQHandler(void)
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
char * hello = "HELLO\n";
while(hello)
{
USART_SendData(USART1, hello);
hello++;
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}
}
}
这样,就可以实现每3秒发送一次字符串“HELLO”到USART1上,达到题目要求。需要注意的是,在调试过程中可能会遇到一些问题,例如串口调试助手不显示字符串,此时可以调整波特率或尝试其他串口调试工具。