资讯详情

STM32串口发送数据和接收数据方式总结

串口发送数据

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的函数写法加以增补。

串口接受数据

串口接受最初应有必定和谈,如发送一帧数据应该有标记标记,也可两个标记都有。

数据的头标识为“\n”既换行符,尾标识为“+”。该函数将串口接受的数据存放在USART_Buffer数组而后判别以后字符是否尾标识,如果是解释接受终了而后再来判别头标识是否假如仍是那末便是咱们想要的数据,接下来就能举行响应数据的处理了假如不是那末就让Usart2_Rx从新接受数据。

  • 这里接收精确数据间接打印进去能够经由过程配置标识而后在主函数内里轮询操纵。

    以上接受方式中缀一次接受一个字符,这在UCOS及时内核体系频仍中缀异常损耗CPU资本,在有些时间咱们需求接受少量数据时且波特率很高的情况下长期中缀会带来一些额定题目。

    #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发送。

    有了以上接受体式格局普通的串口数据处置是没有题目上面再讲一下,在ucosiii应用信号量新闻行列贮存治理方式来处咱们的串口数据来讲一下这类体式格局比照其余体式格局的一些优缺点。

    void task1_task(void *p_arg) { OS_ERR err; OS_MSG_SIZE Usart1_Data_size; u8 *p;  while(1) {  p=(u8*)OSTaskQPend((OS_TICK  )0,     (OS_OPT    )OS_OPT_PEND_BLOCKING,   (OS_MSG_SIZE* )&Usart1_Data_size,   (CPU_TS*   )0,   (OS_ERR*   )&err);   printf("%s\r\n",p);        //打印数据    delay_ms(100);  OSMemPut((OS_MEM* )&UART1_MemPool,       (void*   )p,  (OS_ERR*  )&err);         OSSemPost((OS_SEM* )&SEM_IAR_UART,       (OS_OPT  )OS_OPT_POST_NO_SCHED,  (OS_ERR* )&err);         OSTimeDlyHMSM(0,0,1,500,OS_OPT_TIME_PERIODIC,&err);      }}

    作者能够吃的鱼

    原文:https://blog.csdn.net/qq_35281599

  • 锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

    锐单商城 - 一站式电子元器件采购平台