NB-IOT開發|nbiot開發教程《二》AT指令類模組驅動-STM32串口實現接收不定長度數據

嵌入式開發中我們要時刻保持代碼的高效與整潔

一、前言

        嵌入式開發中我們要時刻保持代碼的高效與整潔。上一節中AT指令模組狀態機的實現需要串口實現接收不定長度數據,本文就是說明具體實現方式。

二、原理

        串口實現接收不定長度數據原理:串口接收中斷接收數據,每次中斷時啓動數據超時定時器(軟件定時器),每次接收到數據更新定時器時間並將數據壓到環形緩衝區中,時間可以爲10ms,當定時器超時時即認爲接收到完整包。

                                                     

        本次串口驅動的封裝是基於cola_os下完成的,關於cola_os的詳細介紹可以參考文章:

        1.嵌入式開發--300行代碼實現操作系統cola_os

        2. 嵌入式開發--實現應用層和硬件層分層管理

        3.嵌入式開發--STM32上實現驅動註冊initcall機制(類linux)

        4.嵌入式開發|高效緩衝器設計(C語言)

三、源代碼

    初始化串口並且初始化串口接收中斷


static void uart1_gpio_init(void)
{
     GPIO_InitTypeDef GPIO_InitStructure;

    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_9;                        
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;                   
    GPIO_Init(GPIOA, &GPIO_InitStructure);                             

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;                         
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;              
    GPIO_Init(GPIOA, &GPIO_InitStructure);                             
}


static void uart1_init(uint32_t bund)
{
    USART_InitTypeDef USART_InitStructure;
    USART_InitStructure.USART_BaudRate = bund;                       
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;       
    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);                          

    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);                     
    USART_Cmd(USART1, ENABLE);                                         
    USART_ClearFlag(USART1,USART_FLAG_RXNE);
}
static void uart1_nvic_init(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
   
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
    NVIC_Init(&NVIC_InitStructure);                  
}

     編寫串口驅動功能函數

static int uart1_write(cola_device_t *dev, int pos, const void *buffer, int size)
{
	uart1_sendnbyte((uint8_t *)buffer,size);
	return size;
}
static int uart1_read(cola_device_t *dev, int pos, void *buffer, int size)
{
	return cola_fifo_read(&uart_fifo,buffer,size);
}
static int uart1_config(cola_device_t *dev, void *args, void *var)
{
	struct serial_configure *cfg = (struct serial_configure *)args;
	if(cfg)
	{
		uart1_init(cfg->baud_rate);
	}
	return 0;
}
static struct cola_device_ops uart1_ops =
{
	.write  = uart1_write,
	.read   = uart1_read,
	.config = uart1_config,
};

串口接收中斷:接收中斷髮生,重啓定時器,將數據放到環形緩衝區中

void USART1_IRQHandler(void)
{
  uint8_t c;
  if((USART1->SR & USART_FLAG_RXNE) == USART_FLAG_RXNE)
  {                                              
    c = (uint8_t)(USART1->DR);
    if(uart1_dev.owner)
    {
        if(uart1_write_slot( &c, 1))
        {
            cola_timer_start(&uart_timer,TIMER_ONE_SHOT,pdMS_TO_TICKS(20));
        }
    }	
  }
}

 

 初始化軟件定時器;

static void uart_timer_cb(uint32_t event)
{
    if(uart1_dev.owner)
    {
        cola_set_event(uart1_dev.owner,SIG_DATA);
    }
}

初始化:

void board_setup_usart(void)
{
#ifdef USING_UART1
    uart1_configuration(115200);
    cola_fifo_init(&uart_fifo,uart_buf,sizeof(uart_buf));
    cola_timer_create(&uart_timer,uart_timer_cb);
    uart1_dev.name = "uart1";
    uart1_dev.dops = &uart1_ops;
    cola_device_register(&uart1_dev);
#endif
}

四、應用層調用與調試

  /********************************  cola os  *********************************
  * @file   : app_uart.c
  * @author : sunny.Bit(QQ 1506564994)
              Email:[email protected]
  * @brief  : cola os		
  ******************************************************************************/
#include "config.h"
#include <string.h>
#include "app.h"

#include "cola_device.h"
#include "cola_os.h"


static task_t uart_task;
static cola_device_t *uart_dev;


static uint8_t tmp[128] = {0};
static void uart_task_cb(uint32_t event)
{
    int err = 0;
    if(event&SIG_DATA)
    {
        err = cola_device_read(uart_dev,0,tmp,sizeof(tmp));
        if(err)
        {
            os_log("UART-RX:%d:",err);
            cola_device_write(uart_dev,0,tmp,err);
            os_log("\r\n");
        }
    }
}

static void uart_dev_init(void)
{
    uart_dev = cola_device_find("uart1");
    assert(uart_dev);
    cola_device_set_owner(uart_dev,&uart_task);
    struct serial_configure cfg;
    cfg.baud_rate = 115200;
    cola_device_cfg(uart_dev,&cfg,0);
}

void uart_task_init(void)
{
    uart_dev_init();
    cola_task_create(&uart_task,uart_task_cb);
}

調試:

這樣實現是不是很簡單。

五、代碼下載

https://github.com/sckuck-bit/nb-iot

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章