七、串口中断方式收发数据和重定向printf
1.新加库函数文件
stm32f10x_usart.h和stm32f10x_usart.c。
USART:同步异步收发器
UART:异步收发器
2.USART/UART知识点
协议:
(1)起始位:一个逻辑0的数据位表示。
(2)数据位:8-9位。
(3)校验位:奇校验、偶校验、无校验。
(4)停止位:0.5、1、1.5、2个逻辑1的数据位表示。
(5)波特率:数据传输的速度,1S发送的比特位数,常用115200、9600。
3.串口1为例使用库函数配置
(1)使能时钟配置端口
1 //1.使能时钟,初始化端口 2 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); 3 4 GPIO_InitTypeDef GPIO_InitStruct; 5 6 GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9; 7 GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;//发送数据端口,复用推挽输出 8 GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz; 9 GPIO_Init(GPIOA,&GPIO_InitStruct); 10 11 GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10; 12 GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;//接收数据端口,浮空输入 13 GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz; 14 GPIO_Init(GPIOA,&GPIO_InitStruct);
(2)使能串口时钟,初始化串口参数
1 //2.使能时钟,配置串口参数 2 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); 3 USART_InitTypeDef USART_InitStruct; 4 5 USART_InitStruct.USART_BaudRate = 115200;//波特率 6 USART_InitStruct.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;//模式,收发模式 7 USART_InitStruct.USART_WordLength = USART_WordLength_8b;//数据位长度,8位 8 USART_InitStruct.USART_Parity = USART_Parity_No;//校验位 9 USART_InitStruct.USART_StopBits = USART_StopBits_1;//一位停止位 10 USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制 11 USART_Init(USART1,&USART_InitStruct);
(3)使能串口,设置中断
1 //3.使能串口设置中断 2 USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//设置接收中断 3 USART_Cmd(USART1,ENABLE);//使能串口
(4)设置NVIC优先级
1 //4.设置中断NVIC 2 NVIC_InitTypeDef NVIC_InitStruct; 3 4 NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn; 5 NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; 6 NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; 7 NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1; 8 NVIC_Init(&NVIC_InitStruct);
(5)编写中断函数接收数据
1 //串口中断函数 2 void USART1_IRQHandler(void) 3 { 4 static int recv_buf_offset=0; 5 uint16_t temp; 6 7 if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET){//接收到数据 8 9 USART_ClearITPendingBit(USART1,USART_IT_RXNE);//软件清除中断状态位 10 11 temp=USART_ReceiveData(USART1); //接收一字节数据 12 recv_buf_temp[recv_buf_offset]=(u8)temp; 13 recv_buf_offset++; 14 15 //接收数据 16 if(recv_buf_temp[recv_buf_offset-1]=='\r'||recv_buf_temp[recv_buf_offset-1]=='\n'){ 17 Send_Data(USART1,recv_buf_temp,recv_buf_offset-1); 18 recv_buf_offset=0; 19 } 20 } 21 }
(6)编写发送数据函数
1 void Send_Data(USART_TypeDef* USARTx,u8* data,u16 data_len) 2 { 3 for(int i=0;i<data_len;i++){ 4 while(USART_GetFlagStatus(USARTx,USART_FLAG_TXE)==RESET);//0表示数据还未转移到移位寄存器,1表示数据已经移动到移位寄存器可以发送数据 5 USART_SendData(USARTx,data[i]); 6 while(USART_GetFlagStatus(USARTx,USART_FLAG_TC)==RESET);//1表示发送完成 7 } 8 }
4.重写printf函数至串口发送数据(法一)
(1)在串口函数中重写fputc函数
1 int fputc(int ch,FILE* f) 2 { 3 while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);//0表示数据还未转移到移位寄存器,1表示数据已经移动到移位寄存器可以发送数据 4 USART_SendData(USART1,(u8)ch); 5 while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);//1表示发送完成 6 return ch; 7 }
(2)设置使用微库
4.重写printf函数至串口发送数据(法二)
(1)串口函数中添加内容不使用半主机模式
1 #pragma inport(__use_no_semihosting);//不使用半主机模式 2 3 //避免使用半主机模式 4 void _sys_exit(int x) 5 { 6 x=x; 7 } 8 9 //标准库需要支持的函数 10 struct __FILE 11 { 12 int handle; 13 }; 14 FILE __stdout;
(2)重写fputs函数
5.c语言关键字
(1)extern:声明变量,函数在其他文件中定义,需要在这个此处引用。
(2)static:声明变量,保存变量最后执行时候的值,初始化一次。
(3)const:声明变量,不可更改值,可以间接的更改。
(4)voliate:告诉编译器,这个值随时可能发生改变,取值时,从变量的内存地址处进行取值。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!