精华内容
下载资源
问答
  • stm32关于浮点数在串口接收函数

    千次阅读 2019-04-11 16:32:08
    stm32关于浮点数在串口接收函数 void USART3_IRQHandler(void) { unsigned char data_3; static char tx_3 = 0; static uint8_t i; if(USART_GetITStatus(USART3,USART_IT_RXNE)!= RESET) { data_3 = USART_Receive...

    stm32关于浮点数在串口接收函数

    void USART3_IRQHandler(void)
    { unsigned char data_3;
    static char tx_3 = 0;
    static uint8_t i;

    if(USART_GetITStatus(USART3,USART_IT_RXNE)!= RESET)
    {
    data_3 = USART_ReceiveData(USART3);
    buffer_3[tx_3]= data_3;
    if(tx_3 == 0) //Ö¡Í·1ÊÇ·ñÊÇ0xff
    {
    tx_3 = (0xff != data_3)?0:tx_3+1;
    }
    else if(tx_3 == 1) //Ö¡Í·1ºóÃæµÄÖ¡Í·2ÊÇ·ñÊÇ0xff
    {
    tx_3 = (0xff != data_3)?0:tx_3+1;
    }
    else if(tx_3 == 2) //Ö¡Í·2ºóÃæµÄÖ¡Í·3ÊÇ·ñÊÇ0xff
    {
    tx_3 = (0xff != data_3)?0:tx_3+1;
    }
    else if(tx_3 == 3) //Ö¡Í·3ºóÃæµÄÖ¡Í·4ÊÇ·ñÊÇ0xff
    {
    tx_3 = (0xff != data_3)?0:tx_3+1;
    }
    else if(tx_3>3)
    {
    tx_3++;
    if (tx_3==12)
    {
    tx_3 = 0;

    					flag_3=1;
    			 }
    			}
    			
    			
    	}
    }
    
    展开全文
  • 程序采用FreeRTOS操作系统,主函数里面调用HAL_UART_Receive_IT接收串口字符,在中断回调函数HAL_UART_RxCpltCallback里面处理串口字符,然后再次调用HAL_UART_Receive_IT继续接收下一个串口字符。用串口调试助手长...

    其实说到底,就是Overrun(USART_SR_ORE)在作怪。

    【问题描述】

    程序采用FreeRTOS操作系统,主函数里面调用HAL_UART_Receive_IT接收串口字符,在中断回调函数HAL_UART_RxCpltCallback里面处理串口字符,然后再次调用HAL_UART_Receive_IT继续接收下一个串口字符。用串口调试助手长时间发送大量数据后,这个循环会突然中断,后面再也不能接收到新的字符。

    【原因分析】

    (一)串口发送函数HAL_UART_Transmit和串口接收函数HAL_UART_Receive_IT不能并发调用,必须用互斥量保护。这是因为,这两个函数内部都有__HAL_LOCK(huart),如果一个线程正在执行HAL_UART_Transmit函数,那么同一时刻另一个线程执行HAL_UART_Receive_IT函数执行__HAL_LOCK会失败,函数返回HAL_BUSY,不能启动数据接收。

      #define __HAL_LOCK(__HANDLE__)                                           \
                                    do{                                        \
                                        if((__HANDLE__)->Lock == HAL_LOCKED)   \
                                        {                                      \
                                           return HAL_BUSY;                    \
                                        }                                      \
                                        else                                   \
                                        {                                      \
                                           (__HANDLE__)->Lock = HAL_LOCKED;    \
                                        }                                      \
                                      }while (0U)

    (二)串口接收函数HAL_UART_Receive_IT调用后,会有三种结果:

    第一种:只调用HAL_UART_RxCpltCallback回调函数
    第二种:HAL_UART_RxCpltCallback和HAL_UART_ErrorCallback回调函数都调用
    第三种:只调用HAL_UART_ErrorCallback回调函数

    长时间(半小时以上)发送大量串口数据时,单片机会因为来不及处理串口数据出现Overrun的错误,此时USART_SR_ORE位为1。
    到了一定时候,当USART_SR寄存器的USART_SR_RXNE为0,且USART_SR_ORE位为1时,就会出现第三种情况,只有HAL_UART_ErrorCallback这个函数会被调用,而且USART_SR_ORE位始终不能自动清除,串口就不能继续接收数据,USART_SR_RXNE位一直为0,这样就产生了死循环。
    函数调用HAL_UART_Receive_IT开始接收数据,而因为ORE=1,马上产生串口中断,进入HAL_UART_ErrorCallback,然后接收自动中止(注意看UART_EndRxTransfer函数,里面只是简单地中止接收)。RXNE位一直为0,永远进不了HAL_UART_RxCpltCallback。而HAL库函数又没有清除ORE位的功能,所以即便再次调用HAL_UART_Receive_IT也是同样的结果。

    用串口调试助手每毫秒发一次数据,长时间不停地发

    如图所示,这是在产生死循环后Keil在中断处理函数中打断点调试得到的结果,isrflags是USART1->SR寄存器的值。寄存器的值为0xd8,说明RXNE=0但ORE=1。

    手册里面可以看到,ORE位是只读位,只能用特殊的方法清除:

    Bit 3 ORE: Overrun error
    This bit is set by hardware when the word currently being received in the shift register is
    ready to be transferred into the RDR register while RXNE=1. An interrupt is generated if
    RXNEIE=1 in the USART_CR1 register. It is cleared by a software sequence (an read to the
    USART_SR register followed by a read to the USART_DR register).
    0: No Overrun error
    1: Overrun error is detected
    Note: When this bit is set, the RDR register content will not be lost but the shift register will be
    overwritten. An interrupt is generated on ORE flag in case of Multi Buffer
    communication if the EIE bit is set.

    清除ORE位的方法是,先读USART_SR寄存器,再读USART_DR寄存器。只要清除了ORE位,就可以打破这种死循环的状态。
    HAL库里面有一个__HAL_UART_FLUSH_DRREGISTER宏可以用来读DR寄存器:
    #define __HAL_UART_FLUSH_DRREGISTER(__HANDLE__) ((__HANDLE__)->Instance->DR)
    所以,我们只要在ORE错误产生时,读一下DR寄存器,就可以解决这个bug,退出这种死循环。

    void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
    {
      if (HAL_UART_GetError(huart) & HAL_UART_ERROR_ORE)
        __HAL_UART_FLUSH_DRREGISTER(huart);
    }

    另外,调试的时候要特别注意,不要把Keil的USART寄存器窗口打开了。因为Keil在读USART1->DR寄存器的时候,会导致USART_SR_RXNE位被清除,程序就可能收不到串口数据。

    【参考程序】

    main.c:

    #include <FreeRTOS.h>
    #include <semphr.h>
    #include <stdio.h>
    #include <stm32f2xx.h>
    #include <task.h>
    #include "common.h"
    
    extern UART_HandleTypeDef huart1;
    RTC_HandleTypeDef hrtc;
    static SemaphoreHandle_t uart_sem;
    
    static void main_task(void *arg)
    {
      RTC_DateTypeDef date;
      RTC_TimeTypeDef time;
      
      hrtc.Instance = RTC;
      while (1)
      {
        HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BCD);
        HAL_RTC_GetDate(&hrtc, &date, RTC_FORMAT_BCD);
        printf_s("ticks=%u, time=20%02x-%x-%x %02x:%02x:%02x\n", HAL_GetTick(), date.Year, date.Month, date.Date, time.Hours, time.Minutes, time.Seconds);
        printf_s("rxstate=%#x, RXNEIE=%d\n", huart1.RxState, __HAL_UART_GET_IT_SOURCE(&huart1, UART_IT_RXNE) != RESET);
        vTaskDelay(pdMS_TO_TICKS(10));
      }
    }
    
    static void uart_task(void *arg)
    {
      uint8_t data;
      BaseType_t bret;
      HAL_StatusTypeDef status;
      
      uart_sem = xSemaphoreCreateBinary();
      HAL_NVIC_SetPriority(USART1_IRQn, 1, 0);
      HAL_NVIC_EnableIRQ(USART1_IRQn);
      HAL_UART_Receive_IT(&huart1, &data, 1);
      while (1)
      {
        bret = xSemaphoreTake(uart_sem, 100);
        if (bret == pdTRUE)
        {
          if (data == 'a')
            printf_s("Received: %c!\n", data);
        }
        
        if (huart1.RxState == HAL_UART_STATE_READY)
        {
          printf_lock();
          status = HAL_UART_Receive_IT(&huart1, &data, 1);
          configASSERT(status == HAL_OK);
          printf_unlock();
        }
      }
    }
    
    int main(void)
    {
      HAL_Init();
      
      clock_init();
      usart_init(115200);
      printf("STM32F217VE USART1\n");
      printf("SystemCoreClock=%u\n", SystemCoreClock);
      
      xTaskCreate_s(main_task, NULL, 2 * configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);
      xTaskCreate_s(uart_task, NULL, 2 * configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);
      vTaskStartScheduler();
      return 0;
    }
    
    void USART1_IRQHandler(void)
    {
      HAL_UART_IRQHandler(&huart1);
    }
    
    void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
    {
      if (HAL_UART_GetError(huart) & HAL_UART_ERROR_ORE)
        __HAL_UART_FLUSH_DRREGISTER(huart);
    }
    
    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    {
      BaseType_t woken = pdFALSE;
      
      if (huart == &huart1)
        xSemaphoreGiveFromISR(uart_sem, &woken);
      portYIELD_FROM_ISR(woken);
    }
    

    common.c(用于printf绑定串口,且不用勾选Use MicroLIB):

    #include <FreeRTOS.h>
    #include <semphr.h>
    #include <stdarg.h>
    #include <stdio.h>
    #include <stm32f2xx.h>
    #include <task.h>
    #include "common.h"
    
    #pragma import(__use_no_semihosting) // 禁用半主机模式 (不然调用printf就会进HardFault)
    
    typedef struct
    {
      TaskFunction_t func;
      void *arg;
    } SafeTask;
    
    FILE __stdout = {1};
    FILE __stderr = {2};
    UART_HandleTypeDef huart1;
    static SemaphoreHandle_t printf_mutex;
    
    /* main函数返回时执行的函数 */
    void _sys_exit(int returncode)
    {
      taskDISABLE_INTERRUPTS();
      printf("Exited! returncode=%d\n", returncode);
      while (1);
    }
    
    void _ttywrch(int ch)
    {
      if (ch == '\n')
        HAL_UART_Transmit(&huart1, (uint8_t *)"\r\n", 2, HAL_MAX_DELAY);
      else
        HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
    }
    
    // HAL库参数错误警告
    #ifdef USE_FULL_ASSERT
    void assert_failed(uint8_t *file, uint32_t line)
    {
      taskDISABLE_INTERRUPTS();
      printf("%s: file %s on line %d\n", __FUNCTION__, file, line);
      while (1);
    }
    #endif
    
    // 配置系统和总线时钟
    void clock_init(void)
    {
      HAL_StatusTypeDef status;
      RCC_ClkInitTypeDef clk = {0};
      RCC_OscInitTypeDef osc = {0};
    
      osc.OscillatorType = RCC_OSCILLATORTYPE_HSE;
      osc.HSEState = RCC_HSE_ON;
      osc.PLL.PLLM = 25;
      osc.PLL.PLLN = 240;
      osc.PLL.PLLP = RCC_PLLP_DIV2;
      osc.PLL.PLLQ = 5;
      osc.PLL.PLLSource = RCC_PLLSOURCE_HSE;
      osc.PLL.PLLState = RCC_PLL_ON;
      status = HAL_RCC_OscConfig(&osc);
      assert_param(status == HAL_OK);
      
      clk.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
      clk.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
      clk.AHBCLKDivider = RCC_SYSCLK_DIV1;
      clk.APB1CLKDivider = RCC_HCLK_DIV4;
      clk.APB2CLKDivider = RCC_HCLK_DIV2;
      HAL_RCC_ClockConfig(&clk, FLASH_LATENCY_3);
    }
    
    void dump_data(const void *data, int len)
    {
      const uint8_t *p = data;
      
      printf_lock();
      while (len--)
        printf("%02X", *p++);
      printf("\n");
      printf_unlock();
    }
    
    int fflush(FILE *stream)
    {
      if (stream->handle == 1 || stream->handle == 2)
        while (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_TC) == RESET);
      return 0;
    }
    
    // printf和perror重定向到串口
    int fputc(int ch, FILE *fp)
    {
      if (fp->handle == 1 || fp->handle == 2)
      {
        _ttywrch(ch);
        return ch;
      }
      return EOF;
    }
    
    void printf_lock(void)
    {
      xSemaphoreTakeRecursive(printf_mutex, portMAX_DELAY);
    }
    
    int printf_s(const char *__restrict format, ...)
    {
      int ret;
      va_list args;
      
      printf_lock();
      __va_start(args, format);
      ret = vprintf(format, args);
      __va_end(args);
      printf_unlock();
      
      return ret;
    }
    
    void printf_unlock(void)
    {
      xSemaphoreGiveRecursive(printf_mutex);
    }
    
    uint32_t sys_now(void)
    {
      return HAL_GetTick();
    }
    
    void usart_init(int baud_rate)
    {
      GPIO_InitTypeDef gpio = {0};
      
      printf_mutex = xSemaphoreCreateRecursiveMutex();
      
      __HAL_RCC_GPIOA_CLK_ENABLE();
      __HAL_RCC_USART1_CLK_ENABLE();
      
      gpio.Alternate = GPIO_AF7_USART1;
      gpio.Mode = GPIO_MODE_AF_PP;
      gpio.Pin = GPIO_PIN_9 | GPIO_PIN_10;
      gpio.Pull = GPIO_NOPULL;
      gpio.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
      HAL_GPIO_Init(GPIOA, &gpio);
      
      huart1.Instance = USART1;
      huart1.Init.BaudRate = baud_rate;
      huart1.Init.Mode = UART_MODE_TX_RX;
      HAL_UART_Init(&huart1);
    }
    
    void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName)
    {
      taskDISABLE_INTERRUPTS();
      printf("Stask overflow!\n");
      while (1);
    }
    
    static void __xTaskCreate_s(void *arg)
    {
      SafeTask task = *(SafeTask *)arg;
      
      vPortFree(arg);
      task.func(task.arg);
      vTaskDelete(NULL);
    }
    
    /* 创建可以使用return语句的任务 */
    BaseType_t xTaskCreate_s(TaskFunction_t pxTaskCode, const char *pcName, configSTACK_DEPTH_TYPE usStackDepth, void *pvParameters, UBaseType_t uxPriority, TaskHandle_t *pxCreatedTask)
    {
      BaseType_t ret;
      SafeTask *p;
      
      p = pvPortMalloc(sizeof(SafeTask));
      if (p == NULL)
        return pdFALSE;
      p->func = pxTaskCode;
      p->arg = pvParameters;
      
      ret = xTaskCreate(__xTaskCreate_s, pcName, usStackDepth, p, uxPriority, pxCreatedTask);
      if (ret == pdFALSE)
        vPortFree(p);
      
      return ret;
    }
    
    void HardFault_Handler(void)
    {
      taskDISABLE_INTERRUPTS();
      printf("Hard Error!\n");
      while (1);
    }
    

    程序的里面有两个任务,一个任务不停地在用printf打印,往串口输出数据,另一个任务专门负责接收串口字符。发送和接收函数用printf_mutex这个互斥量来保护。接收串口字符时等待xSemaphoreTake信号量,若xSemaphoreTake信号量有信号,说明串口收到了字符。然后判断接收是否已停止,若huart1.RxState == HAL_UART_STATE_READY,说明接收已停止,调用HAL_UART_Receive_IT函数重新开始接收。
    在HAL_UART_RxCpltCallback回调函数中使能信号量唤醒接收线程。在HAL_UART_ErrorCallback函数中处理Overrun错误(ORE),及时读取DR寄存器清除ORE位,防止陷入死循环。

    特别注意,while(1)里面的if (huart1.RxState == HAL_UART_STATE_READY)不能放到if (bret == pdTRUE)内,因为调用HAL_UART_Receive_IT后有可能只有HAL_UART_ErrorCallback回调函数被调用,这个时候是没有唤醒信号量的,线程就不能够进入if (bret == pdTRUE)里面,调用HAL_UART_Receive_IT恢复数据接收。

    展开全文
  • Arduino - 串口操作函数与示例代码大全

    万次阅读 多人点赞 2015-12-16 22:36:02
    本文总结了Arduino常用串口操作函数的说明、语法、参数、返回值。根据函数定义编写了示例代码,并通过实验解释了每个函数的具体用法。是对Arduino串口操作函数的较全面总结,可作为工具贴查找使用。

     

    Arduino - 串口操作函数与示例代码大全

     

    本文总结了Arduino常用串口操作函数,函数说明部分来源于Arduino 官网串口使用指南,示例与实验部分为自编。本文是对Arduino串口操作函数的较全面总结,可作为工具贴查找使用。

    1.串口设置

    Serial.begin();  

    说明

     

    开启串口,通常置于setup()函数中。

    语法

    Serial.begin(speed);  

    Serial.begin(speed,config);  

    参数

    speed: 波特率,一般取值300, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600,115200

    config: 设置数据位、校验位和停止位。例如Serial.begin(speed,Serial_8N1);  Serial_8N1中:8表示8个数据位,N表示没有校验,1表示有1个停止位。

    返回

    None

    示例

     

    void setup() { 
    Serial.begin(9600); // opensserial port, sets data rate to 9600 bps 
    }

     

    Serial.end(); 

    说明

    禁止串口传输函数。此时串口传输的pin脚可以作为数字IO脚使用。

    语法 

    Serial.end()

    参数

    None

    返回 

    None

    2.清空串口缓存

    Serial.flush();   

    说明

    1.0版本之前为清空串口缓存,现在该函数作用为等待输出数据传送完毕。如果要清空串口缓存的话,可以使用:while(Serial.read() >= 0)来代替。

    语法 

    Serial.flush ()

    参数

    None

    返回 

    None

    while(Serial.read()>= 0){}

    说明

    因Serial.read()函数读取串口缓存中的一个字符,并删除已读字符。因此可以用这句代码来清空串口缓存。实验代码详见下文代码。

    语法 

    while(Serial.read() >=0){}

    参数

    None

    返回 

    None

    3.输出串口数据

    将打印输出串口数据的函数在这一小节给出,方便大家阅读后面的各个示例代码。

    Serial.print(); 

    说明

    串口输出数据函数,写入字符串数据到串口。

    语法

    Serial.print(val)

    Serial.print(val,format)

    参数

    val: 打印的值,任意数据类型

    format: 输出的数据格式,包括整数类型和浮点型数据的小数点位数。

    示例

     

    • Serial.print(78, BIN) 得到 "1001110"
    • Serial.print(78, OCT) 得到 "116"
    • Serial.print(78, DEC) 得到 "78"
    • Serial.print(78, HEX) 得到 "4E"
    • Serial.print(1.23456, 0) 得到 "1"
    • Serial.print(1.23456, 2) 得到 "1.23"
    • Serial.print(1.23456, 4) 得到 "1.2346"
    • Serial.print('N') 得到 "N"
    • Serial.print("Hello world.") 得到 "Hello world."

    Serial.println();

    说明

    写入字符串数据,并换行。实验代码详见下文。

    语法

    Serial.println(val) 
    Serial.println(val,format)

     

    参数

     

    val: 打印的值,任意数据类型 
    format: 输出的数据格式,包括整数类型和浮点型数据的小数点位数。

    返回 

    字节

    Serial.SerialEvent();

    串口数据准备好时触发的事件函数,即串口数据准备好调用该函数。

    语法 

    Serial.serialEvent{//statements}

    参数 

    statements: 任何有效的语句。

    4.读串口缓存区数据

    Serial.available();

    说明

    判断串口缓冲器的状态函数,用以判断数据是否送达串口。注意使用时通常用delay(100)以保证串口字符接收完毕,即保证Serial.available()返回的是缓冲区准确的可读字节数。

    语法

    Serial.available();

    参数

    None

    返回

    返回缓冲区可读字节数目

    示例

     

    void setup() {
      Serial.begin(9600);
      while(Serial.read()>= 0){}//clear serialbuffer
    }
     
    void loop() {
       if (Serial.available() > 0) {
        delay(100); // 等待数据传完
        int numdata = Serial.available();
        Serial.print("Serial.available = :");
        Serial.println(numdata);
      }
      while(Serial.read()>=0){} //清空串口缓存
    }

    实验结果

     

    Serial.read();

    说明

    读取串口数据,一次读一个字符,读完后删除已读数据。

    语法

    Serial.read();

    参数

    None

    返回

    返回串口缓存中第一个可读字节,当没有可读数据时返回-1,整数类型。

    示例

     

    char comchar;
     
    void setup() {
      Serial.begin(9600);
      while(Serial.read()>= 0){}/ /clear serialbuffer
    }
     
    void loop() {
      // read data from serial port
     
      while(Serial.available()>0){
        comchar = Serial.read();//读串口第一个字节
        Serial.print("Serial.read: ");
        Serial.println(comchar);
        delay(100); 
        }
     }

     

    实验结果

    从实验结果可以看出:Serial.read()每次从串口缓存中读取第一个字符,并将读过的字符删除。

     

    Serial.peek(); 

    说明

    读串口缓存中下一字节的数据(字符型),但不从内部缓存中删除该数据。也就是说,连续的调用peek()将返回同一个字符。而调用read()则会返回下一个字符。

    语法

    Serial.peek();

    参数

    None

    返回

    返回串口缓存中下一字节(字符)的数据,如果没有返回-1,整数int型

    示例

     

    char comchar;
     
    void setup() {
      Serial.begin(9600);
      while(Serial.read()>= 0){}//clear serialbuffer
    }
     
    void loop() {
      // read data from serial port
     
      while(Serial.available()>0){
        comchar = Serial.peek();
        Serial.print("Serial.peek: ");
        Serial.println(comchar);
        delay(100); 
        }
     }

     

    实验结果

     

    从实验结果可以看出:Serial.peek()每次从串口缓存中读取一个字符,并不会将读过的字符删除。第二次读取时仍然为同一个字符。

     

    Serial.readBytes(buffer,length);

    说明

    从串口读取指定长度length的字符到缓存数组buffer。

    语法

    Serial.readBytes(buffer,length);

    参数

    buffer: 缓存变量

    length:设定的读取长度

    返回

    返回存入缓存的字符数,0表示没有有效数据。

    示例

     

    char buffer[18];
    int numdata=0;
     
    void setup() {
      Serial.begin(9600);
      while(Serial.read()>= 0){}//clear serial port
    }
     
    void loop() {
      // read data from serial port
      if(Serial.available()>0){
          delay(100);
          numdata = Serial.readBytes(buffer,3);
          Serial.print("Serial.readBytes:");
          Serial.println(buffer);    
        }
        // clear serial buffer
      while(Serial.read() >= 0){}
      for(int i=0; i<18; i++){
            buffer[i]='\0';
        }
    }

    实验结果

     
    从串口缓存读取指定长度为3的字节。

     

    Serial.readBytesUntil(character,buffer,length);

    说明

    从串口缓存读取指定长度的字符到数组buffer,遇到终止字符character后停止。

    语法

    Serial.readBytesUntil(character ,buffer,length);

    参数

    character : 查找的字符 (char)

    buffer: 存储读取数据的缓存(char[] 或byte[])

    length:设定的读取长度

    返回

    返回存入缓存的字符数,0表示没有有效数据。

    示例

     

    char buffer[18];
    char character = ','; //终止字符
    int numdata=0;
     
    void setup() {
      Serial.begin(9600);
      while(Serial.read()>= 0){}//clear serialport
    }
     
    void loop() {
      // read data from serial port
      if(Serial.available()>0){
          delay(100);
          numdata =Serial.readBytesUntil(character,buffer,3);
          Serial.print("Serial.readBytes:");
          Serial.println(buffer);    
        }
        // clear serial buffer
      while(Serial.read() >= 0){}
      for(int i=0; i<18; i++){
            buffer[i]='\0';
        }
    }

     

    实验结果

     

    从串口缓存中读取3个字符,当遇到","时终止读取。

    Serial.readString();

    说明

    从串口缓存区读取全部数据到一个字符串型变量。

    语法

    Serial.readString();

    参数

    None

    返回

    返回从串口缓存区中读取的一个字符串。

    示例

     

    String comdata = "";
     
    void setup() {
      Serial.begin(9600);
      while(Serial.read()>= 0){} //clear serialbuffer
    }
     
    void loop() {
      // read data from serial port
      if(Serial.available()>0){
          delay(100);
          comdata = Serial.readString();
          Serial.print("Serial.readString:");
          Serial.println(comdata);
        }
        comdata = "";
    }

    实验结果

     

    从实验结果可以看出:Serial.readString()从串口缓存中读取字符至字符串。

     

     

    Serial.readStringUntil();

    说明

    从串口缓存区读取字符到一个字符串型变量,直至读完或遇到某终止字符。

    语法

    Serial.readStringUntil(terminator)

    参数

    terminator:终止字符(cha型)

    返回

    从串口缓存区中读取的整个字符串,直至检测到终止字符。

    示例

     

    String comdata = "";
    char terminator = ',';
    void setup() {
      Serial.begin(9600);
      while(Serial.read()>= 0){} //clear serialbuffer
    }
     
    void loop() {
      // read data from serial port
      if(Serial.available()>0){
          delay(100);
          comdata =Serial.readStringUntil(terminator);
         Serial.print("Serial.readStringUntil: ");
          Serial.println(comdata);
        }
        while(Serial.read()>= 0){}
    }

     

    实验结果

     

     

     

    从串口读取所有字符存放于字符串comdata,直至遇到字符","时终止读取。

    Serial.parseFloat();

    说明

    读串口缓存区第一个有效的浮点型数据,数字将被跳过。当读到第一个非浮点数时函数结束。

    语法

    Serial.parseFloat()

    参数

    None

    返回

    返回串口缓存区第一个有效的浮点型数据,数字将被跳过。

    示例

     

    float comfloat;
     
    void setup() {
      Serial.begin(9600);
      while(Serial.read()>= 0){}//clear serialbuffer
    }
     
    void loop() {
      // read data from serial port
      if(Serial.available()>0){
          delay(100);
          comfloat = Serial.parseFloat();
          Serial.print("Serial.parseFloat:");
          Serial.println(comfloat);
        }
        // clear serial buffer
        while(Serial.read() >= 0){}
    }

    实验结果

     

    从实验结果可以看出:Serial. parseFloat()从串口缓存中读取第一个有效的浮点数,第一个有效数字之前的负号也将被读取,独立的负号将被舍弃。

    Serial.parseInt()

    说明

    从串口接收数据流中读取第一个有效整数(包括负数)。

    注意:

     

    • 非数字的首字符或者负号将被跳过
    • 当可配置的超时值没有读到有效字符时,或者读不到有效整数时,分析停止
    • 如果超时且读不到有效整数时,返回0

     

    语法

    Serial.parseInt()

    Serial.parseInt(charskipChar)

    参数

    skipChar用于在搜索中跳过指定字符(此用法未知)

    返回

    返回下一个有效整型值。

    示例

     

    int comInt;
     
    voidsetup() {
      Serial.begin(9600);
      while(Serial.read()>= 0){}//clear serialbuffer
    }
     
    void loop() {
      // read data from serial port
      if(Serial.available()>0){
          delay(100);
          comInt = Serial.parseInt();
          Serial.print("Serial.parseInt:");
          Serial.println(comInt);
        }
        // clear serial buffer
        while(Serial.read() >= 0){}
    }

    实验结果

     

    从实验结果可以看出:Serial. parseInt()从串口缓存中读取第一个有效整数,第一个有效数字之前的负号也将被读取,独立的负号将被舍弃。

     

     

    5.串口查找指定字符串

    Serial.find()

    说明

    从串口缓存区读取数据,寻找目标字符串target(char型)

    语法

    char target[] = ”目标字符串”;

    Serial.find(target); 

    参数

    target: 目标字符串(char型)

    返回

    找到目标字符串返回真,否则为假

    示例

     

    char target[] ="test";
     
    void setup() {
      Serial.begin(9600);
      while(Serial.read()>= 0){}//clear serialbuffer
    }
     
    void loop() {
      // read data from serial port
       if(Serial.available()>0){
          delay(100);
          if( Serial.find(target)){
             Serial.print("find traget:");
             Serial.println(target);       
            }
         }
        // clear serial buffer
        while(Serial.read() >= 0){}
    }

    实验结果

     


    串口输入字符中只要有test,函数返回真,打印出目标字符串”test”,否则返回假,不打印任何值。

    Serial.findUntil(target,terminal);  

    说明

    从串口缓存区读取数据,寻找目标字符串target(char型数组),直到出现给定字符串terminal(char型),找到为真,否则为假。

    语法

    Serial.findUntil(target,terminal); 

    参数

    target : 目标字符串(char型)

    terminal : 结束搜索字符串(char型)

    返回

    如果在找到终止字符terminal之前找到目标字符target,返回真,否则返回假。

    示例

     

    char target[] ="test";
    char terminal[] ="end";
     
    void setup() {
      Serial.begin(9600);
      while(Serial.read()>= 0){}//clear serialbuffer
    }
     
    void loop() {
      // read data from serial port
       if(Serial.available()>0){
          delay(100);
          if( Serial.findUntil(target,terminal)){
             Serial.print("find traget:");
             Serial.println(target);
            }
         }
        // clear serial buffer
        while(Serial.read() >= 0){}
    }

    实验结果

     

    如果串口缓存中有目标字符”test”,返回真,但如果先遇到终止字符串”end”则函数立即终止,不论字符串后面有没有目标字符”test”。

    6.向串口写数据

    Serial.write();    

    说明

    串口输出数据函数。写二进制数据到串口。

    语法 

    Serial.write(val) 
    Serial.write(str) 
    Serial.write(buf, len)

    参数 

    val: 字节 
    str: 一串字节 
    buf: 字节数组 
    len: buf的长度

    返回 

    字节长度

    示例

     

    void setup(){ 
    Serial.begin(9600); 
    }
    void loop(){ 
      Serial.write(45); // send a byte with thevalue 45 
      int bytesSent = Serial.write(“hello”); //sendthe string “hello” and return the length of the string. 
    }

    转载请注明:http://blog.csdn.net/iracer/article/details/50334041


    新书终于面市啦,《机器学习原理与编程实战》连接原理与实战,感兴趣的同学请移步:

    https://blog.csdn.net/iracer/article/details/116051674?spm=1001.2014.3001.5501

    展开全文
  • simulink 串口接收s函数

    2018-11-18 16:10:22
    simulink 串口接收s函数
  • 简单的串口接收超时函数 类似于select 函数。 设置的超时时间,若在规定的时间内接收到数据,则返回0(接收成功);否则返回-1 适用场景: 给一块设备发送信息,能够立马收到响应信息。 /***********************...

    简单的串口接收超时函数

    类似于select 函数。
    设置的超时时间,若在规定的时间内接收到数据,则返回0(接收成功);否则返回-1

    适用场景:
    给一块设备发送信息,能够立马收到响应信息。

    /*************************************************************************
      * @函数名称    SerialKeyPressed
      * @函数说明   测试超级终端是否有按键按下
      * @输入参数   key:按键
      * @输出参数   无
      * @返回参数   1:正确
                    0:错误
    **************************************************************************/
    uint32_t SerialKeyPressed(uint8_t *key)
    {

        if ( USART_GetFlagStatus(USART1, USART_FLAG_RXNE) != RESET)
        {
            *key = (uint8_t)USART1->DR;
            return 1;
        }
        else
        {
            return 0;
        }
    }


    /************************************************************************
      * @函数名称    Receive_Byte
      * @函数说明   从发送端接收一个字节
      * @输入参数   c: 接收字符
                    timeout: 超时时间
      * @输出参数   无
      * @返回参数   接收的结果
                    0:成功接收
                   -1:时间超时
    *************************************************************************/
    static  int32_t Receive_Byte (uint8_t *c, uint32_t timeout)
    {
        while (timeout-- > 0)
        {
            if (SerialKeyPressed(c) == 1)
            {
                return 0;
            }
        }
        return -1;
    }

     

    展开全文
  • 单片机串口接收发送函数

    千次阅读 2016-01-03 11:12:13
    51单片机 串口接收字符串和发送字符串
  • 串口中断接收函数

    千次阅读 2018-12-04 23:18:09
    /* 用来实现读取接收FIFO中的数据 */ void ReceiveByteUart0(U8 ch) { U32 i; if(GetUartCmdFlag==1)return; // 完成读取 comRbuf[UartDataPointer]=ch; // 读取一个字节 HaveUartData=1; // 串口有数据...
  • 串口接收处理函数

    千次阅读 2016-09-12 06:37:28
    //串口缓冲区 建立一个环形缓冲区,收发 unsigned char xdata UART_Receive_Size=0;//串口缓冲区接收字节数 unsigned char xdata UART_Receive_First=0;//串口缓冲区接收字节开始位置 unsigned char xdata ...
  • epoll函数使用需要用到的头文件: #include &amp;lt;sys/epoll.h&amp;gt; ...串口接收函数: void Uart2::RecvSerial(int fd) { int Ret; int epfd; /* 生成一个epoll专用...
  • C:串口 select函数使用

    千次阅读 2019-02-21 21:43:20
    接收缓存区: /* 接收长度 */ int recv_len;...串口接收函数: void Uart1::RecvSerial(int fd) { fd_set fds; struct timeval timeout={1,0}; //select等待1秒,1秒轮询,要非阻塞就置0 int se...
  • MFC打开串口、关闭串口接口函数的实现,以及收发数据的接口函数实现
  • STM32五个串口同时收发函数配置

    万次阅读 2019-07-03 16:27:23
    //串口中断接收数据的标志位 串口2 串口3 //串口1初始化 void USART1_Configuration(u32 bound) { GPIO_InitTypeDef GPIO_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; USART_InitTypeDef USART_...
  • Arduino常用串口操作函数

    千次阅读 2020-06-06 08:01:11
    本文总结了Arduino常用串口操作函数函数说明部分来源于Arduino 官网串口使用指南,示例与实验部分为自编。本文是对Arduino串口操作函数的较全面总结,可作为工具贴查找使用。 1.串口设置 Serial.begin(); 说明 ...
  • 串口回传函数没有反应的情况 在串口返回函数没有进去时 检查自己使用了什么方式的串口接收?是DMA?还是中断? 一、问题来由 在STM32Cube中,有没有打开对应功能的选项?
  • 串口接受函数

    2019-10-04 11:30:33
    // TODO: 串口消息处理 //常数 值 描述 //comEvSend 1 发送事件。 //comEvReceive 2 接收事件。 //comEvCTS 3 clear-to-send 线变化。 //comEvDSR 4 data-set ready 线变化。 //comEvCD 5 carr...
  • Windows基于串口API函数串口程序开发介绍欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格...
  • matlab串口收发及回调函数编程

    热门讨论 2011-08-20 16:38:27
    matlab创建com对象。并采用中断方式响应回调函数,功能完整,包括创建初始化及关闭销毁。回调函数的格式,实现方法。
  • STM32单片机串口接收中断函数的编写

    千次阅读 2020-02-19 14:53:30
    往往大家都觉得简单,很快就过了,但其实有一些东西是值得深思的,我以前在写程序的时候往往都是发送数据,那么调用重写的printf()函数就可以了,但这次的项目中用到了NRF双全工通讯,这就需要串口收发,...
  • 串口操作函数分析

    千次阅读 2016-08-10 17:25:31
    1、串口的初始化函数 /*  * 初始化UART0  * 115200,8N1,无流控  */ void uart0_init(void) {  GPHCON |= 0xa0; // GPH2,GPH3用作TXD0,RXD0  GPHUP = 0x0c; // GPH2,GPH3内部上拉  ULCON0 = 0x03; //
  • 需要测试代码的可以留下邮箱,或者关注微信公众号 小白技术栈后台回复【cc2530串口回调函数】获取。 CC2530使用MT层实现串口读...在串口接收回调函数MT_UartProcessZToolData()中,Zstack采用状态机接收的方式对串口.
  • 之前一直用STM32CUBE配置工程,但是一用到USART1的DMA接收中断,或者USART1的接收中断,就会出现问题,在之前的调试中发现USART1的DMA与ADC1的DMA有冲突(原因我也不造啊),后来将USART1的DMA接收中断改成USART1的...
  • 1. 寄存器 1.1 状态寄存器 1.2 控制寄存器CR1 1.3 控制寄存器CR3 ... * @brief This function handles UART interrupt request. * @param huart Pointer to a UART_HandleTypeDef structure that contains ...
  • 以前串口中断接收串口数据都是利用了裸机程序,今天把ucos系统在STM32跑了起来,当然也想利用串口中断接收一下串口数据,下面看看具体步骤。 第一步:在OS系统的start任务中,调用USART1的初始化程序。串口1的初始...
  • 本文是关于基本串口收发(中断接收方式)。
  • 串口数据接收与保存: private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { try { int DataLength = s
  • MX串口配置方法见:CubeIDE 利用自带HAL库 串口收发 一、代码自动生成以后的项目及代码结构: main.c中,调用了串口初始化 串口初始化函数赋值了串口的参数 相当于底层的初始化,配置引脚、并开启...
  • then,看下实际工程中的代码(无关代码已经删除,保留关键代码),串口配置为接收中断,输出不用中断方式 串口发送: en_result_t Uart_SendData(uint8_t u8Idx, uint8_t u8Data) { Uart_ClrStatus(u8Idx,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 42,728
精华内容 17,091
关键字:

串口收发函数