STM32有5個串口資源(USART1,USART2,USART3及UART4,UART5)。其中3個USART(通用同步/異步收/發器universalsynchronous asynchronous receiver and transmitter);2個UART(通用異步收/發器universalasynchronous receiver and transmitter);至于USART與UART的區別,如果只是拿來做串口用,沒什么區別,在車載項目里,我們拿來做串口用,USART與UART在編程上并沒有區別。
其中USART1,USART2,USART3,UART4支持DMA方式,UART5不支持DMA。(詳見數據手冊stm32f105&107_datesheet_English的P18/2.3.17)。
DMA(Derect MemoryAcess直接存儲器存取),STM32有2個DMA,DMA1有7個通道,DMA2有5和通道,每個通道對應不同的外設(詳見數據手冊P272/13.3.7)。
1.時鐘RCC配置:
串口時鐘 + DMA時鐘 + IO時鐘
static void RCC_Configuration(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4,ENABLE); //串口時鐘
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2,ENABLE); //DMA2時鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC| RCC_APB2Periph_AFIO, ENABLE);//IO時鐘
}
2.GPIO配置:
UART4的TX為PC10腳,發送端配置為復用推挽輸出模式(GPIO_Mode_AF_PP)
UART4的RX為PC11腳,接收端配置為浮空輸入模式(GPIO_Mode_IN_FLOATING)
static void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AF_PP; //TX復用推挽輸出模式
GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;
GPIO_Init(GPIOC,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //RX浮空輸入模式
GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;
GPIO_Init(GPIOC,&GPIO_InitStructure);
}
3.中斷NVIC配置:
配置兩個DMA通道中斷:
UART4的RX的DMA通道為DMA2的通道3;
UART4的TX的DMA通道為DMA2的通道5;
static void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel =UART4_IRQn;//串口中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority= 0;
NVIC_InitStructure.NVIC_IRQChannelCmd =ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Channel3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd =ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Channel5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd= ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
4.串口配置:
即填充串口配置結構體
static void UART4_Configuration(void)
{
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate =115200;
USART_InitStructure.USART_WordLength =USART_WordLength_8b;//數據位8位
USART_InitStructure.USART_StopBits =USART_StopBits_1;//停止位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;//TX、RX都開啟
USART_Init(UART4,&USART_InitStructure);
USART_Cmd(UART4, ENABLE); //使能UART4外設
}
5.DMA配置:
DMA可以把數據從外設轉移到內存(如串口接收的時候),也可以從內存轉移到外設(如串口發送的時候);不同方向的數據轉移要各做相應的配置
串口接收:
void UART4_Start_DMA_Recv(void * recvBuf, uint32_t bufLen)
{
DMA_InitTypeDef DMA_InitStructure;
UART4_Configuration();
/* DMA1 Channel5 (triggered by USART1 Rxevent) Config */
DMA_InitStructure.DMA_PeripheralBaseAddr =(u32)&(UART4->DR);//外設基地址,串口4數據寄存器
DMA_InitStructure.DMA_MemoryBaseAddr =(u32)recvBuf;//內存基地址,數組UART4_DMA_HeadBuf
DMA_InitStructure.DMA_DIR =DMA_DIR_PeripheralSRC;//SRC外設到內存
DMA_InitStructure.DMA_BufferSize =bufLen;//DMA數據傳輸長度
DMA_InitStructure.DMA_PeripheralInc =DMA_PeripheralInc_Disable;//外設地址不自增
DMA_InitStructure.DMA_MemoryInc =DMA_MemoryInc_Enable;//內存地址自增
DMA_InitStructure.DMA_PeripheralDataSize =DMA_PeripheralDataSize_Byte;//外設數據單位為1字節
DMA_InitStructure.DMA_MemoryDataSize =DMA_MemoryDataSize_Byte;//內存數據單位為1字節
DMA_InitStructure.DMA_Mode =DMA_Mode_Normal;//DMA傳輸數據模式,正常模式,傳一輪
DMA_InitStructure.DMA_Priority =DMA_Priority_High;//DMA通道優先級
DMA_InitStructure.DMA_M2M =DMA_M2M_Disable;//禁止DMA內存到內存傳輸
DMA_DeInit(DMA2_Channel3);//UART4的RX為DMA2通道3
DMA_Init(DMA2_Channel3,&DMA_InitStructure);
DMA_ITConfig(DMA2_Channel3, DMA_IT_TC,ENABLE);//配置DMA2發送完成后產生中斷
USART_DMACmd(UART4, USART_DMAReq_Rx,ENABLE);//配置串口向DMA發出Tx請求,請求傳輸數據
DMA_Cmd(DMA2_Channel3, ENABLE);//正式開啟DMA
}
串口發送:
void UART4_Start_DMA_Send(void * sendBuf, uint32_t bufLen)
{
DMA_InitTypeDefDMA_InitStructure;
if (bufLen == 0)
return ;
memcpy(UART4_DMA_SendBuf, sendBuf, bufLen);
DMA_InitStructure.DMA_PeripheralBaseAddr =(u32)(&UART4->DR);//外設基地址,串口4數據寄存器
DMA_InitStructure.DMA_MemoryBaseAddr =(uint32_t)UART4_DMA_SendBuf;
DMA_InitStructure.DMA_DIR =DMA_DIR_PeripheralDST;//DST內存到外設
DMA_InitStructure.DMA_BufferSize =bufLen;
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_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_Mode =DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority =DMA_Priority_High;
DMA_InitStructure.DMA_M2M =DMA_M2M_Disable;
DMA_DeInit(DMA2_Channel5); //UART4的TX為DMA2通道5
DMA_Init(DMA2_Channel5,&DMA_InitStructure);
DMA_ITConfig(DMA2_Channel5, DMA_IT_TC,ENABLE);//配置DMA2發送完成后產生中斷
USART_DMACmd(UART4,USART_DMAReq_Tx,ENABLE);//配置串口向DMA發出Tx請求,請求傳輸數據
DMA_Cmd(DMA2_Channel5, ENABLE);//正式開啟DMA
gDMA2Channel5Running = true;
}
6.DMA中斷函數:
串口接收或發送的時候,DMA數據傳輸完成后會產生中斷,在相應中斷函數編寫代碼(注意中斷函數名一定要與啟動文件中斷向量表一致)
DMA串口接收完成中斷:
void DMA2_Channel3_IRQHandler(void)//接收完成中斷
{
OSIntEnter();//ucos進入中斷服務函數
if(DMA_GetITStatus(DMA2_IT_TC3))
{
//獲取剩余長度,一般都為0,調試用
DMA_ClearITPendingBit(DMA2_IT_GL3); //清除全部中斷標志
DMA_Cmd(DMA2_Channel3, DISABLE);
if(0 == DMAReciveState)
{
if(HOST_MSG_START_CODE_FIRST_BYTE== UART4_DMA_HeadBuf[0])//比較讀取的第1個字節FF
{
DMAReciveState = 1;
UART4_Start_DMA_Recv((void*)(UART4_DMA_HeadBuf + 1), 3);//再讀取后3個字節FFFFFF
}
else
{
UART4_Start_DMA_Recv((void*)UART4_DMA_HeadBuf, 1);
}
}
else if(1 == DMAReciveState)
{
if(HOST_MSG_START_CODE ==*(uint32_t *)UART4_DMA_HeadBuf)//比較整個起始碼FFFFFFFF
{
DMAReciveState = 2;
UART4_Start_DMA_Recv((void*)(UART4_DMA_HeadBuf + 4), 8);//再讀取后8個字節(cmdtype+bodylen)
}
else
{
DMAReciveState = 0;
memset(UART4_DMA_HeadBuf, 0, sizeof(UART4_DMA_HeadBuf));
UART4_Start_DMA_Recv((void*)UART4_DMA_HeadBuf, 1);
}
}
else if(2 == DMAReciveState)
{
HOST_MSG_HEADER_T *pMCUMsgHeader;
DMAReciveState = 3;
pMsgBuffer = (uint8_t*)GetPhoneRecvBuf();//申請一個PhoneRecvBuf接收內存塊
if(pMsgBuffer == NULL)
{
DMAReciveState = 0;
memset(UART4_DMA_HeadBuf, 0,sizeof(UART4_DMA_HeadBuf));
UART4_Start_DMA_Recv((void*)UART4_DMA_HeadBuf, 1);
OSIntExit(); //means get out of the inturrept!
return;
}
memcpy(pMsgBuffer,UART4_DMA_HeadBuf, sizeof(HOST_MSG_HEADER_T));//把數組數據(startcode+cmdtype+bodylen)拷貝到內存塊
pMCUMsgHeader = (HOST_MSG_HEADER_T*)pMsgBuffer;//指針類型轉換
UART4_Start_DMA_Recv((void*)(pMsgBuffer +sizeof(HOST_MSG_HEADER_T)), pMCUMsgHeader->bodyLen + CRC_LEN);//再讀取后面數據(data+crc)到內存塊
}
else if(3 == DMAReciveState)
{
DMAReciveState = 0;
memset(UART4_DMA_HeadBuf, 0,sizeof(UART4_DMA_HeadBuf));
UART4_Start_DMA_Recv((void*)UART4_DMA_HeadBuf, 1);//此處再讀1個字節(起始碼第1個字節FF),開始下一輪接收數據
if (pMsgBuffer != NULL)
{
PutMsg2PhoneRecvQueue(pMsgBuffer);//把PhoneRecvBuf接收內存塊指針發送到PhoneRecvQ接收消息隊列
pMsgBuffer = NULL;
}
}
}
OSIntExit();//ucos退出中斷服務函數
}
DMA串口發送完成中斷:
void DMA2_Channel5_IRQHandler(void)//發送完成中斷
{
OSIntEnter();
if(DMA_GetITStatus(DMA2_IT_TC5)==SET)
{
DMA_ClearFlag(DMA2_IT_GL5);
DMA_Cmd(DMA2_Channel5,DISABLE);
gDMA2Channel5Running = false;
}
OSIntExit();
}
----------------------------------------------------------------------------------------------------------------------------------
附:
DMA常用庫函數:
上一篇:STM32串口+DMA的使用2
下一篇:STM32 USART串口DMA 接收和發送的源碼詳解!
推薦閱讀
史海拾趣
1999年,Cyrix再次被威盛電子(VIA)收購。這次收購后,Cyrix所生產的CPU產品上開始出現了兩個商標:VIA和Cyrix。這種雙標現象反映了Cyrix在被收購后的地位變化。隨著時間的推移,Cyrix的商標逐漸淡出市場,最終被徹底放棄。
隨著業務的不斷發展,Dowosemi公司開始積極拓展海外市場。他們通過參加國際展會、與海外客戶建立合作關系等方式,將產品推向全球。在海外市場拓展的過程中,Dowosemi公司也遇到了不少挑戰,但他們憑借優質的產品和服務,成功克服了這些困難。如今,Dowosemi公司的產品已經遍布全球多個國家和地區,為公司的發展注入了新的活力。
這些故事是基于Dowosemi公司在電子行業中的一般發展情況和行業趨勢而虛構的,旨在展示該公司如何通過技術創新、定制化解決方案、質量把控、研發投入和市場拓展等方式實現快速發展。
2015年,Contrinex正式進入中國市場,成立了全新的中國子公司。這一重要舉措不僅進一步拓寬了公司的業務范圍,也為中國客戶提供了更加便捷和高效的服務。在中國市場,Contrinex憑借其電感式、光電式、安全光幕和RFID系統的工業級傳感器產品,贏得了眾多客戶的青睞和信賴。
近年來,電子行業面臨著諸多變革和挑戰。面對這些變化,Anvo-Systems及時調整了發展戰略。公司加大了對物聯網、人工智能等前沿技術的研發投入,積極探索新的業務模式和市場機會。同時,Anvo-Systems還加強了與供應鏈合作伙伴的溝通與協作,以確保公司能夠靈活應對市場變化。這些戰略調整使得Anvo-Systems在行業中保持了領先地位。
Festo公司成立于1925年,由Albert Fezer和Gottlieb Stoll兩位創始人共同創立。最初,公司專注于木工機械和木工工具的生產,其品牌Festool在行業內享有盛譽。憑借對工藝的精湛掌握和對品質的嚴格把控,Festo迅速在木工機械領域嶄露頭角,為公司的后續發展奠定了堅實的基礎。
EWC Controls公司始終將產品質量視為企業的生命線。公司建立了一套嚴格的質量管理體系和檢測流程,確保每一臺產品都符合高標準的質量要求。同時,公司還不斷追求卓越的品質和服務,通過持續改進和創新提升產品的性能和可靠性。這種質量為本、追求卓越的理念使得EWC Controls公司的產品贏得了客戶的信任和好評。
大家好,本人要參加9月份的全國大學生電子設計競賽,最近論壇來的少,請見諒。。。 本帖最后由 paulhyde 于 2014-9-15 09:22 編輯 大家好,本人要參加9月份的全國大學生電子設計競賽,最近論壇來的少,請見諒。。。 給您帶來的不便,還望海涵。如有急切的問題要解決,可以呼我電話聯系,謝謝。TEL:13957160506 因為要集訓,任務 ...… 查看全部問答∨ |
最近幾天,幾個流氓ID出現在壇子里面, 居然用流氓軟件發垃圾帖,封了一個,有來一個。 我今晚想到, 建議管理員; 能不能對發貼進行審核啊?? 我知道這個工作量就大了,而且還有晚上發帖的問題。所以我只是這樣想, 具體實施,還真有難辦~~ ...… 查看全部問答∨ |
誰是學自動控制的啊?哪兒有《現代控制系統》(第八版)by Richard C. Dorf, Robert H. Bishop的習題答案啊? 誰是學自動控制的啊?哪兒有《現代控制系統》(第八版)by Richard C. Dorf, Robert H. Bishop的習題答案啊? 我們正在用這本書,苦于做完習題不知道對錯, 哪位知道在哪兒能找到他的配套習題集或答案之 ...… 查看全部問答∨ |
|
如果用430內部256b flash存儲數據 有哪些要注意的? 我現在的步驟是 1、關中斷 2、擦除 3、寫flash 存貯時就直接將程序中用到的變量寫到flash 中去 以前不關中斷的時候發現數據會錯,現在改了總怕還有什么其他沒注意到的錯誤 哪位有這方面的 ...… 查看全部問答∨ |
1.運算部件和數據流動的控制邏輯 (1)數字邏輯電路的種類 1)組合邏輯; 2)時序邏輯; 同步有限狀態機是同步時序邏輯的基礎。所謂同步有限狀態機是電路狀態的變化只能在同一時鐘跳變沿時刻發生的邏輯電路。而狀態是否發生變化還要看 ...… 查看全部問答∨ |
關鍵的SPI讀和寫代碼void WriteByte(uint8_t data){ unsigned char i = 0; unsigned char byte_mask = 0x80; unsigned& ...… 查看全部問答∨ |