STM32
直播中

张鑫

7年用户 864经验值
私信 关注
[问答]

怎样通过printf函数向串口发送我们需要的内容呢

怎样通过printf函数向串口发送我们需要的内容呢?

回帖(1)

彭玉林

2021-12-8 11:28:20
PS:串口通信部分有个东西就是全双工和半双工 ,这个全双工就是两根线,可以同时发送和接收。

  

  

这段引入 printf 函数支持的代码在 usart.h 头文件的最上方,这段代码加入之后便可以通过
printf 函数向串口发送我们需要的内容,方便开发过程中查看代码执行情况以及一些变量值。这
段代码不需要修改,引入到 usart.h 即可。
  //加入以下代码,支持 printf 函数,而不需要选择 use MicroLIB #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(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET); USART_SendData(USART1,(uint8_t)ch); return ch; } #endif   串口通信设置的几个步骤
  

  • 串口时钟使能,GPIO 时钟使能
  • 串口复位
  • GPIO 端口模式设置
  • 串口参数初始化
  • 开启中断并且初始化 NVIC(如果需要开启中断才需要这个步骤)
  • 使能串口
  • 编写中断处理函数

  STM32 的发送与接收是通过数据寄存器 USART_DR 来实现的,这是
一个双寄存器,包含了 TDR 和 RDR。当向该寄存器写数据的时候,串口就会自动发送,当收到数据的时候,也是存在该寄存器内。
STM32 库函数操作 USART_DR 寄存器发送数据的函数是:
  void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);   通过该函数向串口寄存器 USART_DR 写入一个数据。
STM32 库函数操作 USART_DR 寄存器读取串口接收到的数据的函数是:
  uint16_t USART_ReceiveData(USART_TypeDef* USARTx);   通过该函数可以读取串口接受到的数据。
5. 串口状态。串口的状态可以通过状态寄存器 USART_SR 读取。USART_SR 的各位描述如图所示
6.
  

  


  

  

  void USART1_IRQHandler(void) //串口 1 中断服务程序 { u8 Res; #ifdef OS_TICKS_PER_SEC //如果时钟节拍数定义了,说明要使用 ucosII 了. OSIntEnter(); #endif if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是 0x0d 0x0a 结尾) { Res =USART_ReceiveData(USART1);//(USART1->DR); //读取接收到的数据 if((USART_RX_STA&0x8000)==0)//接收未完成 { if(USART_RX_STA&0x4000)//接收到了 0x0d { if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始 else USART_RX_STA|=0x8000; //接收完成了 } else //还没收到 0X0D {  if(Res==0x0d)USART_RX_STA|=0x4000; else { USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ; USART_RX_STA++; if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0; //接收数据错误,重新开始接收 }  } } } #ifdef OS_TICKS_PER_SEC //如果时钟节拍数定义了,说明要使用 ucosII 了. OSIntExit(); #endif }   程序
  main.c #include "led.h" #include "delay.h" #include "key.h" #include "sys.h" #include "usart.h"  int main(void)  {                          u16 t;           u16 len;                 u16 times=0;         delay_init();                     //延时函数初始化                   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级         uart_init(115200);         //串口初始化为115200          LED_Init();                             //LED端口初始化         KEY_Init();          //初始化与按键连接的硬件接口          while(1)         {                 if(USART_RX_STA&0x8000)                 {                                                                    len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度                         printf("rn您发送的消息为:rnrn");                         for(t=0;t
  #include "sys.h" #include "usart.h"           //           //如果使用ucos,则包括下面的头文件即可. #if SYSTEM_SUPPORT_OS #include "includes.h"                                        //ucos 使用           #endif  //V1.3修改说明  //支持适应不同频率下的串口波特率设置. //加入了对printf的支持 //增加了串口接收命令功能. //修正了printf第一个字符丢失的bug //V1.4修改说明 //1,修改串口初始化IO的bug //2,修改了USART_RX_STA,使得串口最大接收字节数为2的14次方 //3,增加了USART_REC_LEN,用于定义串口最大允许接收的字节数(不大于2的14次方) //4,修改了EN_USART1_RX的使能方式 //V1.5修改说明 //1,增加了对UCOSII的支持      // //加入以下代码,支持printf函数,而不需要选择use MicroLIB           #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   /*使用microLib的方法*/  /*  int fputc(int ch, FILE *f) {         USART_SendData(USART1, (uint8_t) ch);          while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {}                 return ch; } int GetKey (void)  {       while (!(USART1->SR & USART_FLAG_RXNE));      return ((int)(USART1->DR & 0x1FF)); } */   #if EN_USART1_RX   //如果使能了接收 //串口1中断服务程序 //注意,读取USARTx->SR能避免莫名其妙的错误            u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节. //接收状态 //bit15,        接收完成标志 //bit14,        接收到0x0d //bit13~0,        接收到的有效字节数目 u16 USART_RX_STA=0;       //接收状态标记              void uart_init(u32 bound){   //GPIO端口设置   GPIO_InitTypeDef GPIO_InitStructure;         USART_InitTypeDef USART_InitStructure;         NVIC_InitTypeDef NVIC_InitStructure;                   RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);        //使能USART1,GPIOA时钟            //USART1_TX   GPIOA.9   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        //复用推挽输出   GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9       //USART1_RX          GPIOA.10初始化   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入   GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10      //Usart1 NVIC 配置   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;                //子优先级3         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                        //IRQ通道使能         NVIC_Init(&NVIC_InitStructure);        //根据指定的参数初始化VIC寄存器       //USART 初始化设置          USART_InitStructure.USART_BaudRate = bound;//串口波特率         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(USART1, &USART_InitStructure); //初始化串口1   USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断   USART_Cmd(USART1, ENABLE);                    //使能串口1   }  void USART1_IRQHandler(void)                        //串口1中断服务程序         {         u8 Res; #if SYSTEM_SUPPORT_OS                 //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.         OSIntEnter();     #endif         if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)                 {                 Res =USART_ReceiveData(USART1);        //读取接收到的数据                                  if((USART_RX_STA&0x8000)==0)//接收未完成                         {                         if(USART_RX_STA&0x4000)//接收到了0x0d                                 {                                 if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始                                 else USART_RX_STA|=0x8000;        //接收完成了                                  }                         else //还没收到0X0D                                 {                                         if(Res==0x0d)USART_RX_STA|=0x4000;                                 else                                         {                                         USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;                                         USART_RX_STA++;                                         if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收                                                   }                                                  }                         }                          }  #if SYSTEM_SUPPORT_OS         //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.         OSIntExit();                                                                                            #endif }  #endif             usart.h #ifndef __USART_H #define __USART_H #include "stdio.h"         #include "sys.h"  //           //V1.3修改说明  //支持适应不同频率下的串口波特率设置. //加入了对printf的支持 //增加了串口接收命令功能. //修正了printf第一个字符丢失的bug //V1.4修改说明 //1,修改串口初始化IO的bug //2,修改了USART_RX_STA,使得串口最大接收字节数为2的14次方 //3,增加了USART_REC_LEN,用于定义串口最大允许接收的字节数(不大于2的14次方) //4,修改了EN_USART1_RX的使能方式 //V1.5修改说明 //1,增加了对UCOSII的支持 #define USART_REC_LEN                          200          //定义最大接收字节数 200 #define EN_USART1_RX                         1                //使能(1)/禁止(0)串口1接收                    extern u8  USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符  extern u16 USART_RX_STA;                         //接收状态标记         //如果想串口中断接收,请不要注释以下宏定义 void uart_init(u32 bound); #endif
举报

更多回帖

×
20
完善资料,
赚取积分