-
2020-12-29 11:30:31
串口发送数据
1、串口发送数据最直接的方式就是标准调用库函数 。
void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);
第一个参数是发送的串口号,第二个参数是要发送的数据了。但是用过的朋友应该觉得不好用,一次只能发送单个字符,所以我们有必要根据这个函数加以扩展:
void Send_data(u8 *s) { while(*s!='\0') { while(USART_GetFlagStatus(USART1,USART_FLAG_TC )==RESET); USART_SendData(USART1,*s); s++; } }
以上程序的形参就是我们调用该函数时要发送的字符串,这里通过循环调用USART_SendData来一 一发送我们的字符串。
while(USART_GetFlagStatus(USART1,USART_FLAG_TC )==RESET);
这句话有必要加,他是用于检查串口是否发送完成的标志,如果不加这句话会发生数据丢失的情况。这个函数只能用于串口1发送。有些时候根据需要,要用到多个串口发送那么就还需要改进这个程序。如下:
void Send_data(USART_TypeDef * USARTx,u8 *s) { while(*s!='\0') { while(USART_GetFlagStatus(USARTx,USART_FLAG_TC )==RESET); USART_SendData(USARTx,*s); s++; } }
这样就可实现任意的串口发送。但有一点,我在使用实时操作系统的时候(如UCOS,Freertos等),需考虑函数重入的问题。
当然也可以简单的实现把该函数复制一下,然后修改串口号也可以避免该问题。然而这个函数不能像printf那样传递多个参数,所以还可以在改进,最终程序如下:void USART_printf ( USART_TypeDef * USARTx, char * Data, ... ) { const char *s; int d; char buf[16]; va_list ap; va_start(ap, Data); while ( * Data != 0 ) // 判断是否到达字符串结束符 { if ( * Data == 0x5c ) //'\' { switch ( *++Data ) { case 'r': //回车符 USART_SendData(USARTx, 0x0d); Data ++; break; case 'n': //换行符 USART_SendData(USARTx, 0x0a); Data ++; break; default: Data ++; break; } } else if ( * Data == '%') { // switch ( *++Data ) { case 's': //字符串 s = va_arg(ap, const char *); for ( ; *s; s++) { USART_SendData(USARTx,*s); while( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET ); } Data++; break; case 'd': //十进制 d = va_arg(ap, int); itoa(d, buf, 10); for (s = buf; *s; s++) { USART_SendData(USARTx,*s); while( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET ); } Data++; break; default: Data++; break; } } else USART_SendData(USARTx, *Data++); while ( USART_GetFlagStatus ( USARTx, USART_FLAG_TXE ) == RESET ); } }
该函数就可以像printf使用可变参数,方便很多。通过观察函数但这个函数只支持了%d,%s的参数,想要支持更多,可以仿照printf的函数写法加以补充。
2、 直接使用printf函数。
很多朋友都知道想要STM32要直接使用printf不行的。需要加上以下的重映射函数;
如果不想添加以上代码,也可以勾选以下的Use MicroLI选项来支持printf函数使用:
串口接受数据
串口接收最后应有一定的协议,如发送一帧数据应该有头标志或尾标志,也可两个标志都有。
这样在处理数据时既能能保证数据的正确接收,也有利于接收完后我们处理数据。串口的配置在这里就不在赘述,这里我以串口2接收中断服务程序函数且接收的数据包含头尾标识为例。#define Max_BUFF_Len 18 unsigned char Uart2_Buffer[Max_BUFF_Len]; unsigned int Uart2_Rx=0; void USART2_IRQHandler() { if(USART_GetITStatus(USART2,USART_IT_RXNE) != RESET) //中断产生 { USART_ClearITPendingBit(USART2,USART_IT_RXNE); //清除中断标志 Uart2_Buffer[Uart2_Rx] = USART_ReceiveData(USART2); //接收串口1数据到buff缓冲区 Uart2_Rx++; if(Uart2_Buffer[Uart2_Rx-1] == 0x0a || Uart2_Rx == Max_BUFF_Len) //如果接收到尾标识是换行符(或者等于最大接受数就清空重新接收) { if(Uart2_Buffer[0] == '+') //检测到头标识是我们需要的 { printf("%s\r\n",Uart2_Buffer); //这里我做打印数据处理 Uart2_Rx=0; } else { Uart2_Rx=0; //不是我们需要的数据或者达到最大接收数则开始重新接收 } } } }
数据的头标识为“\n”既换行符,尾标识为“+”。该函数将串口接收的数据存放在USART_Buffer数组中,然后先判断当前字符是不是尾标识,如果是说明接收完毕,然后再来判断头标识是不是“+”号,如果还是那么就是我们想要的数据,接下来就可以进行相应数据的处理了。但如果不是那么就让Usart2_Rx=0重新接收数据。
这样做的有以下好处:
1.可以接受不定长度的数据,最大接收长度可以通过Max_BUFF_Len来更改
2.可以接受指定的数据
3.防止接收的数据使数组越界
这里我的把接受正确数据直接打印出来,也可以通过设置标识位,然后在主函数里面轮询再操作。以上的接收形式,是中断一次就接收一个字符,这在UCOS等实时内核系统中频繁的中断,非常消耗CPU资源,在有些时候我们需要接收大量数据时且波特率很高的情况下,长时间中断会带来一些额外的问题。
所以以DMA形式配合串口的IDLE(空闲中断)来接受数据将会大大的提高CPU的利用率,减少系统资源的消耗。首先还是先看代码。#define DMA_USART1_RECEIVE_LEN 18 void USART1_IRQHandler(void) { u32 temp = 0; uint16_t i = 0; if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET) { USART1->SR; USART1->DR; //这里我们通过先读SR(状态寄存器)和DR(数据寄存器)来清USART_IT_IDLE标志 DMA_Cmd(DMA1_Channel5,DISABLE); temp = DMA_USART1_RECEIVE_LEN - DMA_GetCurrDataCounter(DMA1_Channel5); //接收的字符串长度=设置的接收长度-剩余DMA缓存大小 for (i = 0;i < temp;i++) { Uart2_Buffer[i] = USART1_RECEIVE_DMABuffer[i]; } //设置传输数据长度 DMA_SetCurrDataCounter(DMA1_Channel5,DMA_USART1_RECEIVE_LEN); //打开DMA DMA_Cmd(DMA1_Channel5,ENABLE); } }
之前的串口中断是一个一个字符的接收,现在改为串口空闲中断,就是一帧数据过来才中断进入一次。而且接收的数据时候是DMA来搬运到我们指定的缓冲区(也就是程序中的USART1_RECEIVE_DMABuffer数组),是不占用CPU时间资源的。
最后在讲下DMA的发送:
#define DMA_USART1_SEND_LEN 64 void DMA_SEND_EN(void) { DMA_Cmd(DMA1_Channel4, DISABLE); DMA_SetCurrDataCounter(DMA1_Channel4,DMA_USART1_SEND_LEN); DMA_Cmd(DMA1_Channel4, ENABLE); }
这里需要注意下DMA_Cmd(DMA1_Channel4,DISABLE)函数需要在设置传输大小之前调用一下,否则不会重新启动DMA发送。
更多相关内容 -
STM32串口发送数据源程序
2020-11-28 21:47:11STM32学习笔记:USART串口 https://blog.csdn.net/thebestleo/article/details/110229383 -
STM32串口发送数据
2019-05-15 15:35:53串口通信经常作为开发调试的工具,所以先介绍下串口通信。 串口通讯(Serial Communication)...目前STM32一般只使用 RXD、TXD 以及 GND 三条信号线,直接传输数据信号。 STM32的串口通信外设有USART和UART。USART是...串口通信经常作为开发调试的工具,所以先介绍下串口通信。
串口通讯(Serial Communication)是一种设备间非常常用的串行通讯方式,因为它简单便捷,大部分电子设备都支持该通讯方式,电子工程师在调试设备时也经常使用该通讯方式输出调试信息。目前STM32一般只使用 RXD、TXD 以及 GND 三条信号线,直接传输数据信号。
STM32的串口通信外设有USART和UART。USART是Universal Synchronous Asynchronous Receiver and Transmitter的缩写,即通用同步异步收发器可以灵活地与外部设备进行全双工数据交换。UART(Universal Asynchronous Receiver and Transmitter)在USART基础上裁减了同步通信功能,只有异步通信。
接口通过三个引脚从外部连接到其它设备(如以下USART框图所示)。任何 USART 双向通信均需要至少两个引脚:接收数据输入引脚 (RX) 和发送数据引脚输出 (TX)。
RX :接收数据输入引脚就是串行数据输入引脚。过采样技术可区分有效输入数据和噪声,从而用于恢复数据。
TX :发送数据输出引脚。如果关闭发送器,该输出引脚模式由其 I/O 端口配置决定。如果使能了发送器但没有待发送的数据,则 TX 引脚处于高电平。在单线和智能卡模式下,该 I/O用于发送和接收数据(USART 电平下,随后在 SW_RX 上接收数据)。
TX和RX分别用PA9和PA10。即使用USART1。
配置串口时,首先要对相应的GPIO口进行初始化,初始化方式和LED灯初始化类似。开启外设时钟,设置端口模式,端口输出类型、输出速度、上下拉、初始输入输出状态。由于USART属于可选功能项,所以两个端口工作模式都为复用功能模式。
GPIO口配置好后,需要选用复用的功能USART1。
从图中可以知道USART1属于寄存器GPIOx_AFRH中的AF7。需要在相应GPIO口写入0111。
接着,设置USART1模式。
根据寄存器说明,配置为过采样16倍、字长8位、不校验,设置一个停止位,设置波特率,使能发送器和接收器。最后使能USART。
波特率指数据信号对载波的调制速率,它用单位时间内载波调制状态改变次数来表示,单位为波特。比特率指单位时间内传输的比特数,单位 bit/s(bps)。对于 USART 波特率与比特率相等。波特率越大,传输速率越快。USART 的发送器和接收器使用相同的波特率。
波特率计算公式
其中,f PLCK 为 USART 时钟,OVER8 为 USART_CR1 寄存器的 OVER8位对应的值,USARTDIV 是一个存放在波特率寄存器(USART_BRR)的一个无符号定点数。其中 DIV_Mantissa[11:0]位定义 USARTDIV 的整数部分,DIV_Fraction[3:0]位定义USARTDIV 的小数部分,DIV_Fraction[3]位只有在 OVER8 位为 0 时有效,否则必须清零。
可通过状态寄存器USART_SR的第七位判断发送数据寄存器是否为空,进行下一步的发送数据。
这个函数虽然可以发送数据,但只能单个发送,如果想发送一个字符串就要多次调用这个函数,所以把这个函数再进行封装。判断要输出的数是否为‘\0’,如果是,则这个数发送结束,不再进行发送数据。这样就可以一次发送一个完整的字符串了。
主函数
usart源文件
usart头文件
最终编译后将程序烧入,STM32发送数据,电脑通过串口助手接收到数据,串口发送数据成功。这样以后就可以很方便的进行调试了。 品略图书馆 http://www.pinlue.com/ http://m.pinlue.com/
-
STM32串口发送字符或字符串控制LED灯
2022-01-19 21:31:131、 发送31,使LED3亮;发送30,使LED3灭; 发送41,使LED4亮;发送40,使LED4灭; 2、 发送LED3_ON,使LED3亮;发送LED3_OF,使LED3灭; 发送LED4_ON,使LED4亮;发送LED4_OF,使LED4灭 -
STM32串口发送数据卡死
2021-01-05 17:50:38记录一个开发日常。DMA发送串口数据”卡死“ 使用DMA发送串口数据记得修改对应DMA中断处理函数。否则程序异常跳转跑飞。记录一个开发日常。DMA发送串口数据”卡死“
使用DMA发送串口数据记得修改对应DMA中断处理函数。否则程序异常跳转跑飞。 -
STM32F4串口发送
2018-05-16 14:51:09基于STM32F407的UART串口数据的发送,用于传输六自由度机械臂的控制指令。 -
STM32串口发送注意问题
2020-08-03 16:12:18本文介绍了使用STM32串口发送数据时由TC状态位引起的错误以及解决方法。 -
STM32串口中断接收发送数据
2018-07-11 10:31:03该程序编写了STM32F103三个串口初始化程序,可快速调用,同时支持接收和发送单个字符和多个字符,并存储数据,方便接收数据后的通信协议校验,支持自定义接收数据最大长度,重写printf函数。 -
stm32串口使用DMA发送数据
2018-07-23 22:48:28通过按键KEY0控制串口1以DMA方式发送数据,按下KEY0,就开始DMA传送,同时在LCD上面显示传送进度。 -
STM32+DMA+串口发送数据(存储器到外设数据传输)
2022-01-05 00:00:19STM32使用DMA功能使串口发送数据的同时,LED灯不停的闪烁 -
STM32F429串口通信程序中十六进制、字符串,格式发送和接收实现
2021-09-27 09:05:06STM32F429串口通信程序中十六进制、字符串,格式发送和接收实现 -
STM32串口发送接收数据
2021-07-14 18:56:39我用的32是stm32f10x最小系统没有UART4和UART5 USART : 通用同步异步收发器 UART : 通用异步收发器 nRTS : 请求发送 nCTS : 请求接收 区别:USART指单片机的一个IO端口模块,可以根据需要配置成同步模式(SPI,IIC),也...1.串口通信
我用的32是stm32f10x最小系统没有UART4和UART5
USART : 通用同步异步收发器
UART : 通用异步收发器
nRTS : 请求发送
nCTS : 请求接收
区别:USART指单片机的一个IO端口模块,可以根据需要配置成同步模式(SPI,IIC),也可以配置成异步模式(UART).可以理解为USART为SPI,IIC对等的”协议”。 UART则不是一个协议,为一个实体。2.串口的结构体
Fck : 串口的时钟(APB1 36M / APB2 72M )
USARTDIV : 无符号的定点数115200= 72 * 1000000/16 * USARTDIV
3.如何配置串口的发送
1.配置时钟: GPIO口的时钟,串口的时钟, 引脚复用的时钟
2.配置GPIO的结构体
3.配置串口的结构体
4.串口的发送4.通过串口向电脑发送ok字符
按照上面的四个步骤进行编写
我们会发现只能一个一个发送字符,比较麻烦,所以后面封装了一个可以发送字符串的函数。
usart.c#include "usart.h" #include "stm32f10x.h" void usart_init(void) { GPIO_InitTypeDef gpio_init; USART_InitTypeDef usartStruct; //1.ÅäÖÃʱÖÓ£ºGPIO¿ÚµÄʱÖÓ£¬Òý½Å¸´ÓõÄʱÖÓ£¬´®¿ÚµÄʱÖÓ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); //2.ÅäÖÃGPIOµÄ½á¹¹Ìå //2.1 TX gpio_init.GPIO_Mode = GPIO_Mode_AF_PP; gpio_init.GPIO_Pin = GPIO_Pin_9; gpio_init.GPIO_Speed = GPIO_Speed_10MHz; GPIO_Init(GPIOA,&gpio_init); //2.2 RX gpio_init.GPIO_Mode = GPIO_Mode_IN_FLOATING; gpio_init.GPIO_Pin = GPIO_Pin_10; GPIO_Init(GPIOA,&gpio_init); //3.ÅäÖô®¿ÚµÄ½á¹¹Ìå usartStruct.USART_BaudRate = 115200; usartStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; usartStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; usartStruct.USART_Parity = USART_Parity_No; usartStruct.USART_StopBits = USART_StopBits_1; usartStruct.USART_WordLength = USART_WordLength_8b; USART_Init(USART1,&usartStruct); USART_Cmd(USART1, ENABLE ); }
usart.h
#include "stm32f10x.h" void usart_init(void);
main.c
#include "stm32f10x.h" #include "led.h" #include "relay.h" #include "shake.h" #include "exti.h" #include "usart.h" void delay(uint16_t time) { uint16_t i =0; while(time--){ i=12000; while(i--); } } int main() { usart_init(); while(1) { USART_SendData(USART1,'n'); //ÏÂÃæUSART_GetFlagStatusΪÁËÅжÏÊý¾Ý¼Ä´æÆ÷ÊÇ·ñΪ¿Õ while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); USART_SendData(USART1,'t'); while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); USART_SendData(USART1,'\n'); while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); delay(1000); } }
5.封装发送字符串函数
注意:在封装发送字符串函数时,while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);是为了把数据发送完
usart.c#include "usart.h" #include "stm32f10x.h" void usart_init(void) { GPIO_InitTypeDef gpio_init; USART_InitTypeDef usartStruct; //1.ÅäÖÃʱÖÓ£ºGPIO¿ÚµÄʱÖÓ£¬Òý½Å¸´ÓõÄʱÖÓ£¬´®¿ÚµÄʱÖÓ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); //2.ÅäÖÃGPIOµÄ½á¹¹Ìå //2.1 TX gpio_init.GPIO_Mode = GPIO_Mode_AF_PP; gpio_init.GPIO_Pin = GPIO_Pin_9; gpio_init.GPIO_Speed = GPIO_Speed_10MHz; GPIO_Init(GPIOA,&gpio_init); //2.2 RX gpio_init.GPIO_Mode = GPIO_Mode_IN_FLOATING; gpio_init.GPIO_Pin = GPIO_Pin_10; GPIO_Init(GPIOA,&gpio_init); //3.ÅäÖô®¿ÚµÄ½á¹¹Ìå usartStruct.USART_BaudRate = 115200; usartStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; usartStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; usartStruct.USART_Parity = USART_Parity_No; usartStruct.USART_StopBits = USART_StopBits_1; usartStruct.USART_WordLength = USART_WordLength_8b; USART_Init(USART1,&usartStruct); USART_Cmd(USART1, ENABLE ); } //·â×°ÁËһϷ¢ËÍ×Ö·û void usartSendByte(USART_TypeDef* USARTx, uint16_t Data) { USART_SendData(USARTx,Data); while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); } //·¢ËÍ×Ö·û´® void usartSendStr(USART_TypeDef* USARTx,char *str) { uint16_t i = 0; do{ usartSendByte(USARTx,*(str+i)); i++; }while(*(str+i) != '\0'); //ÅжÏÊÇ·ñ·¢ËÍÍê while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET); }
usart.h
#include "stm32f10x.h" void usart_init(void); void usartSendByte(USART_TypeDef* USARTx, uint16_t Data); void usartSendStr(USART_TypeDef* USARTx,char *str);
main.c
#include "stm32f10x.h" #include "led.h" #include "relay.h" #include "shake.h" #include "exti.h" #include "usart.h" void delay(uint16_t time) { uint16_t i =0; while(time--){ i=12000; while(i--); } } int main() { usart_init(); while(1) { usartSendStr(USART1,"Finny\r\n"); delay(1000); } }
6.重定向printf串口发送
要使用printf,我们需要添加#include <stdio.h>头文件(学过c的都应该知道吧)
记得要给下图框住的内容打勾哦
stdio.h文件中有一个宏定义fputc,我们需要使用printf只需要重定向fputc就可以使用啦
usart.h#include "stm32f10x.h" #include <stdio.h> void usart_init(void); void usartSendByte(USART_TypeDef* USARTx, uint16_t Data); void usartSendStr(USART_TypeDef* USARTx,char *str);
usart.c
#include "usart.h" #include "stm32f10x.h" void usart_init(void) { GPIO_InitTypeDef gpio_init; USART_InitTypeDef usartStruct; //1.ÅäÖÃʱÖÓ£ºGPIO¿ÚµÄʱÖÓ£¬Òý½Å¸´ÓõÄʱÖÓ£¬´®¿ÚµÄʱÖÓ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); //2.ÅäÖÃGPIOµÄ½á¹¹Ìå //2.1 TX gpio_init.GPIO_Mode = GPIO_Mode_AF_PP; gpio_init.GPIO_Pin = GPIO_Pin_9; gpio_init.GPIO_Speed = GPIO_Speed_10MHz; GPIO_Init(GPIOA,&gpio_init); //2.2 RX gpio_init.GPIO_Mode = GPIO_Mode_IN_FLOATING; gpio_init.GPIO_Pin = GPIO_Pin_10; GPIO_Init(GPIOA,&gpio_init); //3.ÅäÖô®¿ÚµÄ½á¹¹Ìå usartStruct.USART_BaudRate = 115200; usartStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; usartStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; usartStruct.USART_Parity = USART_Parity_No; usartStruct.USART_StopBits = USART_StopBits_1; usartStruct.USART_WordLength = USART_WordLength_8b; USART_Init(USART1,&usartStruct); USART_Cmd(USART1, ENABLE ); } //·â×°ÁËһϷ¢ËÍ×Ö·û void usartSendByte(USART_TypeDef* USARTx, uint16_t Data) { USART_SendData(USARTx,Data); while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET); } //·¢ËÍ×Ö·û´® void usartSendStr(USART_TypeDef* USARTx,char *str) { uint16_t i = 0; do{ usartSendByte(USARTx,*(str+i)); i++; }while(*(str+i) != '\0'); //ÅжÏÊÇ·ñ·¢ËÍÍê while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET); } int fputc(int ch,FILE *f) { USART_SendData(USART1,(uint8_t)ch); while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); return (ch); }
main.c
#include "stm32f10x.h" #include "led.h" #include "relay.h" #include "shake.h" #include "exti.h" #include "usart.h" #include "stdio.h" void delay(uint16_t time) { uint16_t i =0; while(time--){ i=12000; while(i--); } } int main() { usart_init(); GPIO_SetBits(GPIOA, GPIO_Pin_3); GPIO_SetBits(GPIOC, GPIO_Pin_13); while(1) { // usartSendStr(USART1,"°ÂÀï¸ø\r\n"); int i = printf("Finny\r\n"); printf("%d\r\n",i); // putchar('2'); delay(1000); } }
图下为什么i不是5而是7呢,因为\r\n各占了1
重定向fputc不只可以使用printf还可以使用putchar,大伙可以试试呀
7.串口输入控制LED灯开关
输入o让led灯打开并输出Open LED light success,输入c让led灯关闭并输出Close LED light success
提示: main.c中会看见有外部中断的代码,这是之前做震动感应灯的点此进入 STM32 EXTI(外部中断)
led.h#include "stm32f10x.h" void Led_init(void);
led.c
#include "stm32f10x.h" #include "led.h" void Led_init(void) { GPIO_InitTypeDef Led_init; //1.ʹÄÜAPB2µÄʱÖÓGPIO RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); //2.½á¹¹ÌåÅäÖà Led_init.GPIO_Mode = GPIO_Mode_Out_PP; Led_init.GPIO_Pin = GPIO_Pin_13; Led_init.GPIO_Speed = GPIO_Speed_10MHz; GPIO_Init(GPIOC, &Led_init); }
usart.h
#include "stm32f10x.h" #include <stdio.h> void usart_init(void); void usartSendByte(USART_TypeDef* USARTx, uint16_t Data); void usartSendStr(USART_TypeDef* USARTx,char *str);
usart.c
#include "usart.h" #include "stm32f10x.h" void usart_init(void) { GPIO_InitTypeDef gpio_init; USART_InitTypeDef usartStruct; NVIC_InitTypeDef nvic_initStruct; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //1.ÅäÖÃʱÖÓ£ºGPIO¿ÚµÄʱÖÓ£¬Òý½Å¸´ÓõÄʱÖÓ£¬´®¿ÚµÄʱÖÓ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); //2.ÅäÖÃGPIOµÄ½á¹¹Ìå //2.1 TX gpio_init.GPIO_Mode = GPIO_Mode_AF_PP; gpio_init.GPIO_Pin = GPIO_Pin_9; gpio_init.GPIO_Speed = GPIO_Speed_10MHz; GPIO_Init(GPIOA,&gpio_init); //2.2 RX gpio_init.GPIO_Mode = GPIO_Mode_IN_FLOATING; gpio_init.GPIO_Pin = GPIO_Pin_10; GPIO_Init(GPIOA,&gpio_init); //3.ÅäÖô®¿ÚµÄ½á¹¹Ìå usartStruct.USART_BaudRate = 115200; usartStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; usartStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; usartStruct.USART_Parity = USART_Parity_No; usartStruct.USART_StopBits = USART_StopBits_1; usartStruct.USART_WordLength = USART_WordLength_8b; USART_Init(USART1,&usartStruct); USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//ÅäÖô®¿ÚÖÐ¶Ï USART_Cmd(USART1, ENABLE ); nvic_initStruct.NVIC_IRQChannel = USART1_IRQn; nvic_initStruct.NVIC_IRQChannelPreemptionPriority = 1; nvic_initStruct.NVIC_IRQChannelSubPriority = 1; nvic_initStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&nvic_initStruct); } //·â×°ÁËһϷ¢ËÍ×Ö·û void usartSendByte(USART_TypeDef* USARTx, uint16_t Data) { USART_SendData(USARTx,Data); while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET); } //·¢ËÍ×Ö·û´® void usartSendStr(USART_TypeDef* USARTx,char *str) { uint16_t i = 0; do{ usartSendByte(USARTx,*(str+i)); i++; }while(*(str+i) != '\0'); //ÅжÏÊÇ·ñ·¢ËÍÍê while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET); } int fputc(int ch,FILE *f) { USART_SendData(USART1,(uint8_t)ch); while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); return (ch); } int fgetc(FILE *f) { while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET); return (int) USART_ReceiveData(USART1); }
main.c
#include "stm32f10x.h" #include "led.h" #include "relay.h" #include "shake.h" #include "exti.h" #include "usart.h" #include "stdio.h" void delay(uint16_t time) { uint16_t i =0; while(time--){ i=12000; while(i--); } } int main() { Led_init(); Relay_Init(); Shake_init(); exti_init(); usart_init(); //³õʼ»¯Òý½Å GPIO_SetBits(GPIOA, GPIO_Pin_3); GPIO_SetBits(GPIOC, GPIO_Pin_13); } void EXTI1_IRQHandler(void) { if (EXTI_GetITStatus( EXTI_Line1 ) != RESET){// ÅжÏÊÇ·ñ·¢ÉúÖÐ¶Ï GPIO_ResetBits(GPIOA, GPIO_Pin_3); usartSendStr(USART1,"Open light success\r\n"); delay(1000); GPIO_SetBits(GPIOA, GPIO_Pin_3); usartSendStr(USART1,"Close light success\r\n"); } EXTI_ClearFlag(EXTI_Line1); } void USART1_IRQHandler(void) { char temp; if(USART_GetITStatus(USART1,USART_IT_RXNE) != RESET){ temp = USART_ReceiveData(USART1); if(temp == 'o'){ GPIO_ResetBits(GPIOC, GPIO_Pin_13); usartSendStr(USART1,"Open LED light success\r\n"); } if(temp == 'c'){ GPIO_SetBits(GPIOC, GPIO_Pin_13); usartSendStr(USART1,"Close LED light success\r\n"); } } }
遇到的问题
评论区中小鲸鱼uu私信我了一个问题,就是他串口输出乱码
为什么senddata不能发送int的数字,因为将数字转换成ASCII码输出了,至于ASCII码表百度一下吧 -
向STM32串口发送数据的标准函数
2018-06-15 14:03:42向STM32串口发送数据的标准函数 例子:1 void UART_Send_Message(u8 *Data,u8 lenth) { while(lenth--) { USART_SendData(USART2, *Data); ... -
Stm32串口发送数据无法接收到第一个字节
2020-03-24 11:28:19在硬件复位之后读取一下sr寄存器就可以 -
stm32f103串口接收数据后发送数组的数据
2017-07-25 19:07:09stm32f103串口接收数据后发送数组的数据,代码主要在中断函数里,接收到数据后会发送数组中的数据,可以根据要求修改,简单易学,通过了编译 -
STM32串口发彩色图片
2020-03-20 14:53:52正点原子miniSM32采集OV7725图像数据,发送给串口,上位机接收数据,并解析为bmp图片.更多请看博客,【STM32调试(一)】串口发送像素,上位机解析显示。 -
STM32F1向串口一直发送数据
2017-10-24 21:36:12STM32F1向串口一直发送数据,学习串口通信的最好例子,实测通过,主要是用一块板子向第二块板子发送数据,用了2种方法 -
STM32之串口发送宽度为9位的数据
2021-01-06 05:54:22最近为了配置一个芯片使用到了串口发送9位数据位的情况,在此小记一下。 1. 串口硬件和参数初始化 将数据位宽度配置成:UART_WORDLENGTH_9B ,其他参数和常规配置一样。 UART_HandleTypeDef husart3; void HAL_UART_... -
stm32 串口发送字符串第一个字节丢失的问题
2020-08-27 10:55:32使用stm32f205调试串口通讯时,发现一个问题,上电后串口发送字符串的第一个字节会丢失,发送测试数据hello,接收端收到的数据为:ello,第一个字符丢失。用示波器抓取波形,发现第一个数据的波型也是丢失的。 -
STM32踩坑:STM32串口发送乱码问题
2020-10-16 09:36:05STM32串口发送乱码问题 小编是一个嵌入式初学者,才学没多久,将近两个月的样子,在学习过程中遇到了一些问题,在这里给大家分享一下解决方案。 今天要分享的问题是 STM32 串口发送字符串,但是在调试助手上面接收到... -
stm32串口发送数据出现问题
2015-11-18 09:32:12在用stm32向上位机发送串口数据的时候,发现发送的个数和上位机接收到的数据个数不匹配,后来发现是延时的问题,在发送的时候加个延时就可以了! -
STM32串口实验+自定义协议接收16进制数据+发送1个(2个)字符+发送字符串函数.zip
2022-01-03 15:34:53STM32串口使用自定义协议接收一串十六进制数据并进行储存 提取十六进制数据的两个字节转化为十进制数据 发送一个字节函数 发送两个字节函数 发送字符串函数 重定向printf函数 重定向scanf函数 -
STM32串口接受和发送数据的程序(USART/UART)
2021-09-06 17:26:03本实验中,STM32通过串口1和串口2上位机对话,STM32通过串口1在收到上位机发过来的字符串(以回车换行结束)后,通过串口2原原本本的返回给上位机。 一、配置USART1 #include "sys.h" #include "usart1.h" #if SYSTEM_... -
基于STM32F103 处理器的串口发送数据程序
2017-11-05 17:39:56基于STM32F103 处理器的串口发送数据程序,使用输入输出重定向,在程序中可以使用 printf scanf -
STM32串口DMA收发数据示例
2018-02-08 21:14:37以STM32为基础展示如何使用DMA收发串口数据 STM32F103 DMA收发 经过稳定测试 初始化后直接用 -
labview与stm32串口通信与控制
2022-02-27 16:12:491.电机测速 2.STM32与labview串口通信 -
记录应用STM32串口收发数据时出现的问题
2021-10-16 22:42:34发送数据为:sf1233445a。 sf,a,为起始与末尾校验位。 显示结果如下: 既接收数组为空。 串口中断代码如下: void USART1_IRQHandler(void) //串口1全局中断服务函数 { u8 temp; if( USART_GetITStatus(USART1...