這兩天調試STM32F103的開發板,需要實現接收一定長度連續的數據。當數據流接收結束的時候,觸發串口接收中斷。計算數據流長度,并將數據傳到內存中。
main.c
// DMA 存儲器到外設(串口)數據傳輸實驗
#include "stm32f10x.h"
#include "bsp_usart_dma.h"
#include "bsp_led.h"
extern uint8_t ReceiveBuff[RECEIVEBUFF_SIZE];
static void Delay(__IO u32 nCount);
/**
* @brief 主函數
* @param 無
* @retval 無
*/
int main(void)
{
uint16_t i;
/* 初始化USART */
USART_Config();
/* 配置使用DMA模式 */
USARTx_DMA_Config();
USARTx_NVIC_Config();
/* 配置RGB彩色燈 */
LED_GPIO_Config();
//printf("\r\n USART1 DMA TX 測試 \r\n");
/*填充將要發送的數據*/
for(i=0;i { ReceiveBuff[i] = 'P'; } /*為演示DMA持續運行而CPU還能處理其它事情,持續使用DMA發送數據,量非常大, *長時間運行可能會導致電腦端串口調試助手會卡死,鼠標亂飛的情況, *或把DMA配置中的循環模式改為單次模式*/ /* 此時CPU是空閑的,可以干其他的事情 */ //例如同時控制LED while(1) { LED1_TOGGLE Delay(0xFFFFF); } } static void Delay(__IO uint32_t nCount) //簡單的延時函數 { for(; nCount != 0; nCount--); } /*********************************************END OF FILE**********************/ bsp_usart_dma.c #include "bsp_usart_dma.h" uint8_t ReceiveBuff[RECEIVEBUFF_SIZE]; /** * @brief USART GPIO 配置,工作參數配置 * @param 無 * @retval 無 */ void USART_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; // 打開串口GPIO的時鐘 DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE); // 打開串口外設的時鐘 DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE); // 將USART Tx的GPIO配置為推挽復用模式 GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure); // 將USART Rx的GPIO配置為浮空輸入模式 GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure); // 配置串口的工作參數 // 配置波特率 USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE; // 配置 針數據字長 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(DEBUG_USARTx, &USART_InitStructure); //開啟空閑中斷 USART_ITConfig(DEBUG_USARTx, USART_IT_IDLE, ENABLE); /* 使能USART1 DMA接收 */ USART_DMACmd(DEBUG_USARTx, USART_DMAReq_Rx, ENABLE); // 使能串口 USART_Cmd(DEBUG_USARTx, ENABLE); } /***************** 發送一個字節 **********************/ void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch) { /* 發送一個字節數據到USART */ USART_SendData(pUSARTx,ch); /* 等待發送數據寄存器為空 */ while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET); } /****************** 發送8位的數組 ************************/ void Usart_SendArray( USART_TypeDef * pUSARTx, uint8_t *array, uint16_t num) { uint8_t i; for(i=0; i { /* 發送一個字節數據到USART */ Usart_SendByte(pUSARTx,array[i]); } /* 等待發送完成 */ while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET); } /***************** 發送字符串 **********************/ void Usart_SendString( USART_TypeDef * pUSARTx, char *str) { unsigned int k=0; do { Usart_SendByte( pUSARTx, *(str + k) ); k++; } while(*(str + k)!='\0'); /* 等待發送完成 */ while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET) {} } /***************** 發送一個16位數 **********************/ void Usart_SendHalfWord( USART_TypeDef * pUSARTx, uint16_t ch) { uint8_t temp_h, temp_l; /* 取出高八位 */ temp_h = (ch&0XFF00)>>8; /* 取出低八位 */ temp_l = ch&0XFF; /* 發送高八位 */ USART_SendData(pUSARTx,temp_h); while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET); /* 發送低八位 */ USART_SendData(pUSARTx,temp_l); while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET); } ///重定向c庫函數printf到串口,重定向后可使用printf函數 int fputc(int ch, FILE *f) { /* 發送一個字節數據到串口 */ USART_SendData(DEBUG_USARTx, (uint8_t) ch); /* 等待發送完畢 */ while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET); return (ch); } ///重定向c庫函數scanf到串口,重寫向后可使用scanf、getchar等函數 int fgetc(FILE *f) { /* 等待串口輸入數據 */ while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) == RESET); return (int)USART_ReceiveData(DEBUG_USARTx); } /** * @brief USARTx RX NVIC 配置,外設到內存(DR->USART1) * @param 無 * @retval 無 */ void USARTx_DMA_Config(void) { DMA_InitTypeDef DMA_InitStructure; // 開啟DMA時鐘 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // 設置DMA源地址:串口數據寄存器地址*/ DMA_InitStructure.DMA_PeripheralBaseAddr = USART_DR_ADDRESS; // 內存地址(要傳輸的變量的指針) DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ReceiveBuff; // 方向:從外設到內存 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; // 傳輸大小 DMA_InitStructure.DMA_BufferSize = RECEIVEBUFF_SIZE; // 外設地址不增 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 內存地址自增 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // 外設數據單位 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; // 內存數據單位 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; // DMA模式,一次或者循環模式 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ; //DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; // 優先級:中 DMA_InitStructure.DMA_Priority = DMA_Priority_High; // 禁止內存到內存的傳輸 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; // 配置DMA通道 DMA_Init(USART_RX_DMA_CHANNEL, &DMA_InitStructure); // 使能DMA DMA_Cmd (USART_RX_DMA_CHANNEL,ENABLE); } //重新恢復DMA指針 void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx) { DMA_Cmd(DMA_CHx, DISABLE ); //關閉USART1 TX DMA1所指示的通道 DMA_SetCurrDataCounter(DMA_CHx, RECEIVEBUFF_SIZE);//DMA通道的DMA緩存的大小 DMA_Cmd(DMA_CHx, ENABLE); //打開USART1 TX DMA1所指示的通道 } /** * @brief USARTx RX NVIC 配置,外設到內存(DR->USART1) * @param 無 * @retval 無 */ void USARTx_NVIC_Config(void) { NVIC_InitTypeDef NVIC_InitStructure; /* Configure the NVIC Preemption Priority Bits */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3); /* Enable the USART Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } //串口中斷函數 void USART1_IRQHandler(void) //串口1中斷服務程序 { uint8_t Usart1_Rec_Cnt; if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET) //接收中斷(接收到的數據必須是0x0d 0x0a結尾) { USART_ReceiveData(USART1);//讀取數據注意:這句必須要,否則不能夠清除中斷標志位。 Usart1_Rec_Cnt = RECEIVEBUFF_SIZE - DMA_GetCurrDataCounter(DMA1_Channel5); //算出接本幀數據長度 //***********幀數據處理函數************// printf ("Thelenght:%d\r\n",Usart1_Rec_Cnt); printf ("The data:\r\n"); Usart_SendArray(DEBUG_USARTx, ReceiveBuff, RECEIVEBUFF_SIZE); printf ("\r\nOver! \r\n"); //*************************************// USART_ClearITPendingBit(USART1,USART_IT_IDLE); //清除中斷標志 MYDMA_Enable(DMA1_Channel5); //恢復DMA指針,等待下一次的接收 } } bsp_usart_dma.h #ifndef __USARTDMA_H #define __USARTDMA_H #include "stm32f10x.h" #include // 串口工作參數宏定義 #define DEBUG_USARTx USART1 #define DEBUG_USART_CLK RCC_APB2Periph_USART1 #define DEBUG_USART_APBxClkCmd RCC_APB2PeriphClockCmd #define DEBUG_USART_BAUDRATE 115200 // USART GPIO 引腳宏定義 #define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOA) #define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd #define DEBUG_USART_TX_GPIO_PORT GPIOA #define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_9 #define DEBUG_USART_RX_GPIO_PORT GPIOA #define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_10 // 串口對應的DMA請求通道 #define USART_TX_DMA_CHANNEL DMA1_Channel4 #define USART_RX_DMA_CHANNEL DMA1_Channel5 // 外設寄存器地址 #define USART_DR_ADDRESS (USART1_BASE+0x04) // 一次發送的數據量 #define RECEIVEBUFF_SIZE 50 void USART_Config(void); void USARTx_DMA_Config(void); #endif /* __USARTDMA_H */ 編譯后成功運行,運行結果:
上一篇:STM32之串口DMA接收不定長數據
下一篇:STM32F103之DMA實驗,內存通過DMA向串口1發送數據
推薦閱讀
史海拾趣
Altmustech公司的創立源于一次技術突破。創始人李博士帶領的團隊成功研發了一款高效能、低成本的半導體芯片,這一創新技術解決了當時電子行業面臨的能效問題,迅速引起了市場的關注。隨著技術的不斷完善和產品的推出,Altmustech逐漸在半導體市場上嶄露頭角,為公司的快速發展奠定了堅實的基礎。
隨著技術的不斷成熟和市場的擴大,ADC開始將業務擴展到更廣泛的領域。公司不僅繼續深耕探測器領域,還逐漸拓展到傳感器、測量儀器等多個領域。通過不斷推出多樣化的產品,ADC成功滿足了不同客戶的需求,并在市場上取得了良好的口碑。
為了進一步提升競爭力,ADC積極尋求與其他企業的戰略合作。通過與業界領先的企業建立合作關系,ADC成功整合了各方資源,共同研發新技術、新產品。這些合作不僅加速了ADC的技術創新步伐,也為其帶來了更多的商業機會。
Advanced Power Solutions公司自創立之初,就致力于電源管理技術的研發。在一次偶然的實驗中,公司的研發團隊發現了一種新的電源轉換技術,可以顯著提高能源利用效率。公司迅速投入資源,完善這項技術,并成功將其應用于新產品中。這款高效能的產品迅速在市場上獲得了認可,為公司帶來了可觀的收益,也奠定了公司在電源管理領域的領先地位。
隨著全球環保意識的提高,Advanced Power Solutions公司開始關注電源管理技術的環保性能。公司投入大量資源研發綠色、低碳的電源管理產品,并成功推出了一系列符合環保標準的新產品。這些產品不僅受到了消費者的歡迎,也贏得了政府和環保組織的認可。公司的環保理念和創新精神為其贏得了良好的社會聲譽。
Advanced Power Solutions公司自創立之初,就致力于電源管理技術的研發。在一次偶然的實驗中,公司的研發團隊發現了一種新的電源轉換技術,可以顯著提高能源利用效率。公司迅速投入資源,完善這項技術,并成功將其應用于新產品中。這款高效能的產品迅速在市場上獲得了認可,為公司帶來了可觀的收益,也奠定了公司在電源管理領域的領先地位。
在verilog中模塊都是全局的,所以可以直接在模塊外使用內部的寄存器,下面的task中實現測試系統中的復位等待 // purpose: procedure to wait until the root port is done being reset task req_intf_wait_reset_end; ...… 查看全部問答∨ |
請教:WINCE5.0上已經可以使用3G上網卡,原來WinMobile基于GPRS的程序如何移植過來? 怎樣才能讓原來基于GPRS的程序運行于3G上網卡上? 我正在WINCE 5.0上做一個3G無線上網卡的項目,已經可以用IE上網了; 但是以前的程序是基于GPRS的,調用的網絡接口不一樣,原來調用的網絡接口有這些: ConnMgrApiReadyEvent、ConnMgrConnection ...… 查看全部問答∨ |
//所需頭文件 #include "includes.h" // 封裝的頭文件、宏定義、變量、函數聲明 /*************************全局變量 ...… 查看全部問答∨ |
|
STM32 Nucleo與其藍牙擴展板X-Nucleo-IDB04A1進程 其實前幾天便收到了電子工程世界郵寄過來的板卡,只是當是項止催得急便沒有進行開發,今天把漂亮的藍牙擴展板與Nucleo板組合在了一起開始研究。根據板卡包裝上的網址,我到ST網站上下載了很多資料,包括板卡簡介,原理圖,BOM表,生產加工文件,還 ...… 查看全部問答∨ |