STM32應用DMA——串列埠收發不定長資料
STM32應用DMA——串列埠收發不定長資料
使用STM32自帶DMA傳輸資料,可以減輕CPU負擔,只需設定一些引數即可傳送想要傳送的資料,以下是STM32F1系列晶片測試過的部分程式碼,可實現DMA串列埠收發資料。
一、初始化部分
STM32 HAL庫
void uart2_init(uint32_t m_u32bound)
{
//01-GPIO配置
GPIO_InitTypeDef GPIO_InitStruct = {0};
//02-開啟時鐘
__HAL_RCC_USART2_CLK_ENABLE(); //啟動串列埠2時鐘
__HAL_RCC_GPIOA_CLK_ENABLE(); //啟動GPIOA時鐘
//03-配置引腳
GPIO_InitStruct.Pin = GPIO_PIN_2; //USART1_TX PA.2
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; //推完複用模式
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; //高速配置
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); //PA2初始化
GPIO_InitStruct.Pin = GPIO_PIN_3; //USART1_RX PA.3
GPIO_InitStruct.Mode = GPIO_MODE_INPUT; //輸入模式:浮空輸入
GPIO_InitStruct.Pull = GPIO_NOPULL; //沒有上下拉
HAL_GPIO_Init(GPIOA,&GPIO_InitStruct); //PA3初始化
//04-設定串列埠中斷
HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART2_IRQn);
//05-USART 配置
I_huart2.Instance = USART2;
I_huart2.Init.BaudRate = m_u32bound; //波特率
I_huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE; //沒有硬體控制流
I_huart2.Init.Mode = UART_MODE_TX_RX; //收發模式
I_huart2.Init.StopBits = UART_STOPBITS_1; //停止位1位
I_huart2.Init.Parity = UART_PARITY_NONE; //無奇偶校驗位
I_huart2.Init.OverSampling = UART_OVERSAMPLING_16; //
I_huart2.Init.WordLength = UART_WORDLENGTH_8B; //資料位:8個
if(HAL_UART_Init(&I_huart2)!=HAL_OK) //初始化串列埠
while(1);
//04-設定中斷優先順序
HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART2_IRQn);
//05-啟動DMA1時鐘
__HAL_RCC_DMA1_CLK_ENABLE();
//07-DMA1 USART2_RX
hdma_usart2_tx.Instance = DMA1_Channel7; //通道7
hdma_usart2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; //外設到記憶體
hdma_usart2_tx.Init.PeriphInc = DMA_PINC_DISABLE; //外設地址不增長
hdma_usart2_tx.Init.MemInc = DMA_MINC_ENABLE; //記憶體地址增長模式
hdma_usart2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; //位元組對齊
hdma_usart2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; //位元組對齊
hdma_usart2_tx.Init.Mode = DMA_NORMAL; //正常模式
hdma_usart2_tx.Init.Priority = DMA_PRIORITY_HIGH; //傳輸等級:高
if (HAL_DMA_Init(&hdma_usart2_tx) != HAL_OK)
while(1);
//06-DMA1 USART2_RX
hdma_usart2_rx.Instance = DMA1_Channel6; //通道6
hdma_usart2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; //記憶體到外設
hdma_usart2_rx.Init.PeriphInc = DMA_PINC_DISABLE; //外設地址不增長
hdma_usart2_rx.Init.MemInc = DMA_MINC_ENABLE; //記憶體地址增長
hdma_usart2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;//位元組對齊
hdma_usart2_rx.Init.MemDataAlignment = DMA_PDATAALIGN_BYTE; //位元組對齊
hdma_usart2_rx.Init.Mode = DMA_CIRCULAR; //迴圈模式
hdma_usart2_rx.Init.Priority = DMA_PRIORITY_LOW; //傳輸等級:低
if (HAL_DMA_Init(&hdma_usart2_rx) != HAL_OK)
while(1);
//07-開啟傳送完成中斷
__HAL_UART_ENABLE_IT(&I_huart2, UART_IT_TC); //傳送完成中斷
//08-開啟DMA接收
HAL_DMA_Start(&hdma_usart2_rx,(uint32_t)&USART2->DR,(uint32_t)I_USART2.u8rxbuff,BUFFMAX);
SET_BIT(I_huart2.Instance->CR3, USART_CR3_DMAR);//USART2請求 DMA啟動
//09-開啟DMA傳送
HAL_DMA_Start(&hdma_usart2_tx, (uint32_t)I_USART2.u8txbuff,(uint32_t)&USART2->DR, 0);
SET_BIT(I_huart2.Instance->CR3, USART_CR3_DMAT);//USART2請求 DMA啟動
}
二、串列埠中斷部分(傳送資料部分)
這個需要開啟串列埠傳送完成中斷,當DMA往串列埠送資料送完後,串列埠會產生髮送完成中斷。
//串列埠2傳送中斷
void USART2_IRQHandler(void)
{
if((USART2->SR & UART_FLAG_TC)!=RESET)
{
//當DMA傳輸資料完成以後,就會進入一次這個中斷
USART2->SR = ~(UART_FLAG_TC);
u8txmode = SEND_FINISH//此處設定:傳送完成標誌
}
}
三、傳送資料函式
每當呼叫這個函式就會,要求DMA傳送一段資料給串列埠,接下來等待進入串列埠傳送中斷後,就已經完成傳送
//入口引數
//txlen : 傳送資料長度
void USART2_TxdSend(uint16_t u16txlen)
{
__HAL_DMA_DISABLE(&hdma_usart2_tx); //暫停DMA
__HAL_DMA_GET_COUNTER(&hdma_usart2_tx) = u16txlen; //設定傳送資料長度
__HAL_DMA_ENABLE(&hdma_usart2_tx); //啟動DMA
__HAL_UART_CLEAR_FLAG(&I_huart2, UART_FLAG_TC); //清除傳送中斷
}
三、開啟定時器
開啟定時器的目的是希望,資料能夠完成傳送過來,當超過一定時間後,接收完成
void Timer4_Init(void)
{
TIM_MasterConfigTypeDef sMasterConfig = {0};
//01-定時器4時鐘
__HAL_RCC_TIM4_CLK_ENABLE();
//02-定時器4
I_htim4.Instance = TIM4; //TIM4¶¨Ê±Æ÷
I_htim4.Init.Prescaler = 35; //Ô¤·ÖƵϵÊý
I_htim4.Init.CounterMode = TIM_COUNTERMODE_UP; //ÏòÉϼÆÊý
I_htim4.Init.Period = 10000; //ÖØ×°ÔØÖµ 0 ->> 10000
I_htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; //²»·ÖƵ
I_htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; //ʹÄÜÖØÐÂ×°ÔØ
if (HAL_TIM_Base_Init(&I_htim4) != HAL_OK)
while(1);
//03-設定中斷
HAL_NVIC_SetPriority(TIM4_IRQn, 3, 0);
HAL_NVIC_EnableIRQ(TIM4_IRQn);
//05-¶¨Ê±Æ÷´¥·¢Ô´ÉèÖÃ
sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE; //更新中斷
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&I_htim4, &sMasterConfig) != HAL_OK)
while(1);
//06-清除中斷標誌位
__HAL_TIM_CLEAR_FLAG(&I_htim4,TIM_FLAG_UPDATE);
//07-開啟定時器中斷
HAL_TIM_Base_Start_IT(&I_htim4);
}
四、定時器中斷(接收資料部分)
#define RECE_FINISH 0 //接收資料完成標誌
#define RECE_ING 1 //正在就收資料
#define RECE_ILDE 2 //空閒狀態
uint16_t u16rxp; //現在接收資料長度
uint16_t u16timer; //接收計時器
uint8_t u8rxmode; //接收狀態
//定時器4(每1毫秒進入一次中斷)
void TIM4_IRQHandler(void)
{
//獲取定時器更新
if(__HAL_TIM_GET_FLAG(&I_htim4,TIM_FLAG_UPDATE) != RESET)
{
//清除定時器中斷
__HAL_TIM_CLEAR_FLAG(&I_htim4,TIM_FLAG_UPDATE);
if(u8rxmode != RECE_FINISH)
{
if(u16rxp != (BUFFMAX - DMA1_Channel6->CNDTR))
{//查詢接收資料有變化
u16timer =0;
u16rxp = (BUFFMAX - DMA1_Channel6->CNDTR); //當前已經獲取的資料長度
}
if(u16timer < 20 )
u16timer ++; //接收資料計數
if(u16timer ==20)
{//超過一定時間,DMA沒傳過任何資料
u16timer =0;
u8rxmode = RECE_FINISH;
__HAL_DMA_DISABLE(&hdma_usart2_rx); //暫停DMA2
DMA1_Channel6->CNDTR = BUFFMAX; //寫入緩衝區長度
__HAL_DMA_ENABLE(&hdma_usart2_rx); //啟動DMA2
}
}
}
}
相關文章
- STM32使用DMA傳送串列埠資料串列埠
- STM32串列埠DMA接收雙緩衝串列埠
- 【STM32】串列埠串列埠
- LED發光二極體,串列埠收發資料、按鍵控制串列埠
- Uart進行的串列埠收發串列埠
- Linux串列埠程式收發16進位制資料錯誤Linux串列埠
- 串列埠收發UART(Verilog HDL)串列埠
- STM32 串列埠功能詳解串列埠
- STM32 HAL 庫實現乒乓快取加空閒中斷的串列埠 DMA 收發機制,輕鬆跑上 2M 波特率快取串列埠
- 串列埠收發字元轉換為整數串列埠字元
- STM32串列埠通訊串列埠
- stm32DMA+訊息佇列實現串列埠資料接收不丟包佇列串列埠
- 串列埠資料抓取及串列埠通訊模擬串列埠
- stm32配合xshell串列埠輸入串列埠
- 如何使用Java串列埠進行資料通訊及應用案例Java串列埠
- 在Java中操作串列埠實現簡訊收發Java串列埠
- STM32傳送串列埠資料丟失位元組的解決辦法串列埠
- Arduino下的STM32的串列埠通訊UI串列埠
- STM32 HAL庫之串列埠詳細篇串列埠
- STM32串列埠列印的那些知識串列埠
- QT串列埠助手(三):資料接收QT串列埠
- python讀取串列埠 資料Python串列埠
- STM32與物聯網02-網路資料收發
- stm32筆記[16]-使用usb-cdc串列埠.md筆記串列埠
- VC++串列埠程式設計之簡訊應用開發(轉)C++串列埠程式設計
- ESP32 wifi 串列埠轉發資料 UART micropythonWiFi串列埠Python
- QT串列埠助手(四):資料傳送QT串列埠
- 虛擬串列埠工具MCGS開發除錯的靈活應用教程串列埠除錯
- FPGA入門筆記011_B——搭建串列埠收發與存取雙口RAM簡易應用系統FPGA筆記串列埠
- STM32使用串列埠實現USART1傳送字串串列埠字串
- 基於Atmega8微控制器的串列埠收發程式串列埠
- 7寸串列埠屏在破壁機上的應用串列埠
- 7寸串列埠屏在微波爐上的應用串列埠
- 串列埠通訊應用程式的解決方案 (轉)串列埠
- Linux 串列埠程式設計 串列埠裝置程式開發Linux串列埠程式設計
- 不定引數的應用
- 初步使用Ardunio IDE實現STM32的串列埠通訊IDE串列埠
- stm32 DMA2D知識點