定时器中断与串口的使用
功能实现:通过定时器中断,每隔100ms通过串口返回电脑一个数据。
以下代码是在正点原子代码基础上修改的。
main.c
#include "sys.h"
#include "usart.h"
#include "timer.h"
extern void MY_USART1_Init(void);
int main()
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2
TIM3_Int_Init(999,7199);//定时100ms (999+1)*7200/72000
MY_USART1_Init();
while(1);
}
usart.c
#include "usart.h"
#include "sys.h"
//想要使用printf函数,需要加入以下代码
#if 1
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE
{
int handle;
};
FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
_sys_exit(int x)
{
x = x;
}
//重定义fputc函数
int fputc(int ch, FILE *f)
{
while((USART1->SR&0X40)==0);//循环发送,直到发送完毕
USART1->DR = (u8) ch;
return ch;
}
#endif
void MY_USART1_Init()
{
GPIO_InitTypeDef GPIO_InitStrue;
USART_InitTypeDef USART_InitStrue;
NVIC_InitTypeDef NVIC_InitStrue;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//串口时钟使能
//USART1_TX GPIOA.9
GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStrue.GPIO_Pin=GPIO_Pin_9;
GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&GPIO_InitStrue);
//USART1_RX GPIOA.10初始化
GPIO_InitStrue.GPIO_Mode=GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_InitStrue.GPIO_Pin=GPIO_Pin_10;
GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&GPIO_InitStrue); //GPIO端口初始化
USART_InitStrue.USART_BaudRate=115200; //波特率设置
USART_InitStrue.USART_HardwareFlowControl=USART_HardwareFlowControl_None; //无硬件数据流控制
USART_InitStrue.USART_Mode=USART_Mode_Tx|USART_Mode_Rx; //设置收发模式
USART_InitStrue.USART_Parity=USART_Parity_No; //无奇偶校验位
USART_InitStrue.USART_StopBits=USART_StopBits_1; //停止位设置为1
USART_InitStrue.USART_WordLength=USART_WordLength_8b; // 字长设置为8位
USART_Init(USART1,&USART_InitStrue); //串口初始化
USART_Cmd(USART1,ENABLE);//使能串口
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//开启接收中断,开启中断服务函数,设置中断类型
NVIC_InitStrue.NVIC_IRQChannel=USART1_IRQn;
NVIC_InitStrue.NVIC_IRQChannelCmd=ENABLE; //通道使能
NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=1; //抢占优先级1
NVIC_InitStrue.NVIC_IRQChannelSubPriority=1; //子优先级1
NVIC_Init(&NVIC_InitStrue); //中断优先级初始化
}
timer.c
#include "timer.h"
#include "usart.h"
void TIM3_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStrue;
NVIC_InitTypeDef NVIC_InitStrue;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//使能定时器时钟
TIM_TimeBaseInitStrue.TIM_Period=arr;//设置自动装载值
TIM_TimeBaseInitStrue.TIM_Prescaler=psc;//设置预分频系数
TIM_TimeBaseInitStrue.TIM_CounterMode=TIM_CounterMode_Up;//设置向上计数模式
TIM_TimeBaseInitStrue.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStrue);//初始化定时器
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);//开启定时器的更新中断
NVIC_InitStrue.NVIC_IRQChannel=TIM3_IRQn;//TIM3中断;
NVIC_InitStrue.NVIC_IRQChannelCmd=ENABLE;//IRQ通道使能
NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=0;//先占优先级0级
NVIC_InitStrue.NVIC_IRQChannelSubPriority=3;//子优先级3
NVIC_Init (&NVIC_InitStrue);//初始化NVIC寄存器
TIM_Cmd(TIM3,ENABLE);//使能定时器
}
void TIM3_IRQHandler(void)//中断服务函数
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET)//==1 !=RESET
{
printf("\n\r1\r\n");//发送1到电脑
TIM_ClearITPendingBit(TIM3,TIM_IT_Update);//清除标志位
}
//TIM_ClearITPendingBit(TIM3,TIM_IT_Update);//清除标志位
}
效果如下:
写在最后
写程序的时候,如果usart.c文件是自己写的话,一定要将SYSTEM文件夹下原有的的usart.c文件删除,否则会一直报错。
还有主函数中的MY_USART1_Init(),明明已经在usart.h中声明了,但编译时还是会显示function declared implicitly,后来根据网上的提供的方法,在main.c中用extern外部声明,然后编译就通过了。