一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

STM32

 奔跑的瓦力 2019-01-28

前言  

  之前的一篇文章中我為了可以實(shí)現(xiàn)USART接收任意長度的數(shù)據(jù),對HAL的庫進(jìn)行了修改,可以實(shí)現(xiàn)接收以0x0a結(jié)尾的任意長度數(shù)據(jù),即認(rèn)為接收到0x0a時(shí)接收結(jié)束,見鏈接:HAL USART接收任意長度。
  然而,上述這種方法并不合適,原則上HAL庫一般不去修改,不便于其他人移植程序,降低了程序中庫的適用性,這是很不好的習(xí)慣,所以這種方法并不可取。
  后查資料得知STM32中還可以利用DMA的方式實(shí)現(xiàn)串口的任意長度數(shù)據(jù)的接收,故開始學(xué)習(xí)DMA+串口接收任意長度的數(shù)據(jù)這種方式。

cubeMX軟件配置過程

首先,第一步都是進(jìn)行時(shí)鐘樹的配置,配置好系統(tǒng)的時(shí)鐘,不同的芯片配置不同的時(shí)鐘頻率,如圖。
這里寫圖片描述
接著,配置USART1,選擇異步asynchronous,軟件自動配置了PA9和PA10管腳。
這里寫圖片描述
然后,繼續(xù)添加USART1的發(fā)送和接收DMA,其余默認(rèn)即可。
這里寫圖片描述
接著,勾選上USART1的中斷使能。
這里寫圖片描述
最后,生成MDK-ARM V5版本環(huán)境的程序。
這里寫圖片描述

UASRT串口程序修改

//添加變量,為什么用關(guān)鍵字volatile見鏈接:[鏈接](http://blog.csdn.net/u014470361/article/details/78830147)
volatile uint8_t rx_len=0;
volatile uint8_t recv_end_flag=0;
uint8_t rx_buffer[200];
static void MX_USART1_UART_Init(void)
{

  huart1.Instance = USART1;
  huart1.Init.BaudRate = 115200;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
  //上面的usart配置代碼為cubemx自動生成的,在下方添加使能idle中斷和打開串口DMA接收語句
    __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);//使能idle中斷
    HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);//打開DMA接收,數(shù)據(jù)存入rx_buffer數(shù)組中。 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

接下來修改串口中斷函數(shù)。

void USART1_IRQHandler(void)
{
    uint32_t tmp_flag = 0;
    uint32_t temp;
    tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE); //獲取IDLE標(biāo)志位
    if((tmp_flag != RESET))//idle標(biāo)志被置位
    { 
        __HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除標(biāo)志位
        temp = huart1.Instance->SR;  //清除狀態(tài)寄存器SR,讀取SR寄存器可以實(shí)現(xiàn)清除SR寄存器的功能
        temp = huart1.Instance->DR; //讀取數(shù)據(jù)寄存器中的數(shù)據(jù)
        HAL_UART_DMAStop(&huart1); //
        temp  = hdma_usart1_rx.Instance->NDTR;// 獲取DMA中未傳輸?shù)臄?shù)據(jù)個(gè)數(shù),NDTR寄存器分析見下面
        rx_len =  BUFFER_SIZE - temp; //總計(jì)數(shù)減去未傳輸?shù)臄?shù)據(jù)個(gè)數(shù),得到已經(jīng)接收的數(shù)據(jù)個(gè)數(shù)
        recv_end_flag = 1;  // 接受完成標(biāo)志位置1    
     }
  HAL_UART_IRQHandler(&huart1);

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

DMA通道結(jié)構(gòu)體中定義了NDTR寄存器,那為什么是未傳輸?shù)臄?shù)據(jù)數(shù)呢,STM32的中文手冊給出了該寄存器的具體說明。

typedef struct
{
  __IO uint32_t CR;     /*!< DMA stream x configuration register      */
  __IO uint32_t NDTR;   /*!< DMA stream x **number of data register**     */
  __IO uint32_t PAR;    /*!< DMA stream x peripheral address register */
  __IO uint32_t M0AR;   /*!< DMA stream x memory 0 address register   */
  __IO uint32_t M1AR;   /*!< DMA stream x memory 1 address register   */
  __IO uint32_t FCR;    /*!< DMA stream x FIFO control register       */
} DMA_Stream_TypeDef;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

這里寫圖片描述
接著,編寫主函數(shù)中串口中斷的處理函數(shù)。

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART1_UART_Init();
  while (1)
  {
        if(recv_end_flag ==1)
        {
            printf("rx_len=%d\r\n",rx_len);//打印接收長度
            HAL_UART_Transmit(&huart1,rx_buffer, rx_len,200);接收數(shù)據(jù)打印出來
            for(uint8_t i=0;i<rx_len;i++)
                {
                    rx_buffer[i]=0;//清接收緩存
                }
            rx_len=0;//清除計(jì)數(shù)
            recv_end_flag=0;//清除接收結(jié)束標(biāo)志位
        }
        HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);//重新打開DMA接收     
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

程序的運(yùn)行效果如下圖所示 ,輸入任意長度數(shù)據(jù),串口打印出接收的數(shù)據(jù)長度并打印出接收的數(shù)據(jù)。本程序設(shè)置的接收長度最大BUFFER_SIZE是200,若想接收更長的數(shù)據(jù),也可以把BUFFER_SIZE和數(shù)組長度改大。
這里寫圖片描述

DMA參數(shù)和函數(shù)解析

DMA的基本原理、參數(shù)和函數(shù)解析在下一篇文章進(jìn)行分析(鏈接)。

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    欧美精品久久99九九| 欧美小黄片在线一级观看| 日本黄色高清视频久久| 男女午夜视频在线观看免费| 日韩欧美综合在线播放| 国产精品久久香蕉国产线| 国产精品视频久久一区| 国产一级内射麻豆91| 91久久精品中文内射| 草草视频福利在线观看| 欧美一本在线免费观看| 日本亚洲精品在线观看| 日本不卡在线视频你懂的| 国内外激情免费在线视频| 大香蕉久草网一区二区三区| 国产精品成人免费精品自在线观看 | 午夜亚洲少妇福利诱惑| 中文字幕禁断介一区二区| 99久久精品免费看国产高清| 九九热精彩视频在线免费| 国产成人精品一区二区在线看| 五月激情婷婷丁香六月网| 亚洲国产黄色精品在线观看| 亚洲黑人精品一区二区欧美| 日韩国产传媒在线精品| 大香蕉大香蕉手机在线视频| 熟妇久久人妻中文字幕| 欧美日韩国产另类一区二区| 在线免费国产一区二区三区| 麻豆蜜桃星空传媒在线观看| 美女激情免费在线观看| 日本免费一级黄色录像| 国内精品伊人久久久av高清| 亚洲视频一区二区久久久| 久久综合日韩精品免费观看| 午夜久久精品福利视频| 亚洲综合日韩精品欧美综合区| 尤物天堂av一区二区| 国产欧美精品对白性色| 日本中文在线不卡视频| 午夜精品久久久99热连载|