精华内容
下载资源
问答
  • STM32串口发送数据和接收数据方式总结
    千次阅读
    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学习笔记: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/

     

     

     

    展开全文
  • 1、 发送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串口发送数据时由TC状态位引起的错误以及解决方法。
  • 该程序编写了STM32F103三个串口初始化程序,可快速调用,同时支持接收和发送单个字符和多个字符,并存储数据,方便接收数据后的通信协议校验,支持自定义接收数据最大长度,重写printf函数。
  • 通过按键KEY0控制串口1以DMA方式发送数据,按下KEY0,就开始DMA传送,同时在LCD上面显示传送进度。
  • STM32使用DMA功能使串口发送数据的同时,LED灯不停的闪烁
  • STM32F429串口通信程序中十六进制、字符串,格式发送和接收实现
  • STM32串口发送接收数据

    万次阅读 多人点赞 2021-07-14 18:56:39
    我用的32stm32f10x最小系统没有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); ...
  • 在硬件复位之后读取一下sr寄存器就可以
  • stm32f103串口接收数据发送数组的数据,代码主要在中断函数里,接收到数据后会发送数组中的数据,可以根据要求修改,简单易学,通过了编译
  • STM32串口发彩色图片

    2020-03-20 14:53:52
    正点原子miniSM32采集OV7725图像数据,发送给串口,上位机接收数据,并解析为bmp图片.更多请看博客,【STM32调试(一)】串口发送像素,上位机解析显示。
  • STM32F1向串口一直发送数据,学习串口通信的最好例子,实测通过,主要是用一块板子向第二块板子发送数据,用了2种方法
  • 最近为了配置一个芯片使用到了串口发送9位数据位的情况,在此小记一下。 1. 串口硬件和参数初始化 将数据位宽度配置成:UART_WORDLENGTH_9B ,其他参数和常规配置一样。 UART_HandleTypeDef husart3; void HAL_UART_...
  • 使用stm32f205调试串口通讯时,发现一个问题,上电后串口发送字符串的第一个字节会丢失,发送测试数据hello,接收端收到的数据为:ello,第一个字符丢失。用示波器抓取波形,发现第一个数据的波型也是丢失的。
  • STM32踩坑:STM32串口发送乱码问题

    千次阅读 2020-10-16 09:36:05
    STM32串口发送乱码问题 小编是一个嵌入式初学者,才学没多久,将近两个月的样子,在学习过程中遇到了一些问题,在这里给大家分享一下解决方案。 今天要分享的问题是 STM32 串口发送字符串,但是在调试助手上面接收到...
  • stm32串口发送数据出现问题

    千次阅读 2015-11-18 09:32:12
    在用stm32向上位机发送串口数据的时候,发现发送的个数和上位机接收到的数据个数不匹配,后来发现是延时的问题,在发送的时候加个延时就可以了!
  • STM32串口使用自定义协议接收一串十六进制数据并进行储存 提取十六进制数据的两个字节转化为十进制数据 发送一个字节函数 发送两个字节函数 发送字符串函数 重定向printf函数 重定向scanf函数
  • 本实验中,STM32通过串口1和串口2上位机对话,STM32通过串口1在收到上位机发过来的字符串(以回车换行结束)后,通过串口2原原本本的返回给上位机。 一、配置USART1 #include "sys.h" #include "usart1.h" #if SYSTEM_...
  • 基于STM32F103 处理器的串口发送数据程序,使用输入输出重定向,在程序中可以使用 printf scanf
  • STM32为基础展示如何使用DMA收发串口数据 STM32F103 DMA收发 经过稳定测试 初始化后直接用
  • 1.电机测速 2.STM32与labview串口通信
  • 发送数据为:sf1233445a。 sf,a,为起始与末尾校验位。 显示结果如下: 既接收数组为空。 串口中断代码如下: void USART1_IRQHandler(void) //串口1全局中断服务函数 { u8 temp; if( USART_GetITStatus(USART1...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 21,001
精华内容 8,400
关键字:

stm32串口发送数据