完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
1:概述 1.1:本篇实现串口驱动,实现printf函数的重定向,实现串口的中断接受和发送,效仿modbus协议中的3.5T超时机制,判断是否接受完毕; 1.2:如果串口仅仅是实现一个控制台,打印一些debug数据,使用printf函数(串口发送数据忙等待),如果是需要用串口进行外设设备的控制,比如串口GPRS模块,需使用串口中断进行控制,因为受限于串口的传输速率,如果使用忙等待发送数据,会阻塞主程序中的其它任务; 1.3:使用sysclk作为超时定时器,sysclk的中断优先级需高于串口中断; 1.4:除过使用3.5T超时时间判断接受数据是否完成外,还可使用ASCLL码的形式,利用字符操作库函数,自定义串口通信协议; 1.5:开发板:stm32f103zert 软件环境:KEIL MKD5 1.6:115200 波特率,间隔1ms发送字符串 "PassWord",主程序将接收到"PassWord"后返回"123456rn",测试主程序响应迅速,不丢帧; 2:代码 main.c #include "stm32f10x.h" #include "usart_init.h" #include "timer.h" #include "Sys_Driver.h" unsigned int baud[5] = {9600,14400,19200,56000,115200}; unsigned int T_35 = 0; //串口发送3.5个字节的时间,由波特率得出,单位为ms int main(void) { T_35 = 3.5*(10000000/baud[4]); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断优先级分组 Usart_Init(baud[4]); //串口初始化 SysTick_Init(INT_1US,SysTick_CLKSource_HCLK_Div8); //sysclk初始化,设置1ms中断 timer_set(&usart_timer,T_35); //定义一个串口计时器 while(1) { if(Start_Receive_Flag == 1) { if(timer_expired(&usart_timer) == 1) //3.5T时间到达,一条串口数据接受成功 { Start_Receive_Flag = 0; Usart_Handle_Func(); } } } } usart_init.c #include "usart_init.h" u8 Usart_Receive_Ok = 0; u8 Start_Receive_Flag = 0; u8 Usart_TX_Buff[TX_RE_BUFF_LENGTH]; u8 Usart_RX_Buff[TX_RE_BUFF_LENGTH]; COMx_Define CYCLE; /*******************printf()函数重定向***************/ //发送函数 int fputc(int ch, FILE *f) { USART_SendData(USART2, (unsigned char) ch); while (!(USART2->SR & USART_FLAG_TXE)); return (ch); } //接受函数 int fgetc(FILE *f) { while (!(USART2->SR & USART_FLAG_RXNE)); return USART_ReceiveData(USART2); } void Usart_Init(u32 baud) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能USART2,GPIOA时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); //使能USART2,GPIOA时钟 //USART2_TX PA.2 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); //USART2_RX PA.3 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); //USART2 NVIC 配置 NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0; //抢占优先级2 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //子优先级2 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器 //USART 初始化设置 USART_InitStructure.USART_BaudRate = baud; USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式 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(USART2, &USART_InitStructure); //初始化串口 USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); //开启发送完成中断和接收完成中断 USART_ITConfig(USART2,USART_IT_TC,ENABLE); //开启发送完成中断和接收完成中断 USART_Cmd(USART2, ENABLE); //使能串口 } void Usart_Send_Byte(u8 data) { Usart_TX_Buff[CYCLE.TX_write] = data; //装发送缓冲区 if(++CYCLE.TX_write == TX_RE_BUFF_LENGTH) CYCLE.TX_write = 0; if(CYCLE.TX_busy == 0) //发送空闲 { CYCLE.TX_busy = 1; USART_SendData(USART2,Usart_TX_Buff[CYCLE.TX_read]); //想串口发送数据,触发中断 if(++CYCLE.TX_read == TX_RE_BUFF_LENGTH) CYCLE.TX_read = 0; } } /*串口发送函数*/ void Usart_Send_Data(u8 *ptr,u8 num) { if(num == 0) //发送字符串 { for(;*ptr!=' |