一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

CKS32F4xx系列產(chǎn)品串口DMA傳輸

中科芯MCU ? 來源:中科芯MCU ? 作者:中科芯MCU ? 2023-04-10 11:18 ? 次閱讀

在上一講,我們講過CKS32F4xx系列的6個(gè)串口都支持DMA傳輸。因此本節(jié)我們對(duì)CKS32F4xx系列的DMA進(jìn)行介紹,同時(shí)利用DMA對(duì)串口數(shù)據(jù)進(jìn)行傳輸。

DMA介紹

DMA,全稱為:Direct Memory Access,即直接存儲(chǔ)器訪問。DMA傳輸方式無需CPU直接控制傳輸,也沒有中斷處理方式那樣保留現(xiàn)場和恢復(fù)現(xiàn)場的過程,通過硬件為RAM與I/O設(shè)備開辟一條直接傳送數(shù)據(jù)的通路,能使CPU的效率大為提高。

CKS32F4xx系列最多有2個(gè)DMA控制器(DMA1和DMA2),共16個(gè)數(shù)據(jù)流(每個(gè)控制器8個(gè)),每個(gè)數(shù)據(jù)流總共可以有多達(dá)8個(gè)通道(或稱請(qǐng)求)。CKS32F4xx系列的DMA支持外設(shè)到存儲(chǔ)器傳輸、存儲(chǔ)器到外設(shè)傳輸和存儲(chǔ)器到存儲(chǔ)器傳輸三種傳輸模式。,存儲(chǔ)器一般是指片內(nèi)SRAM、外部存儲(chǔ)器、片內(nèi)Flash等等。

外設(shè)到存儲(chǔ)器:把外設(shè)數(shù)據(jù)寄存器內(nèi)容轉(zhuǎn)移到指定的內(nèi)存空間。比如進(jìn)行ADC采集時(shí)我們可以利用DMA傳輸把AD轉(zhuǎn)換的數(shù)據(jù)轉(zhuǎn)移到我們定義的存儲(chǔ)區(qū)中。

存儲(chǔ)器到外設(shè):把特定存儲(chǔ)區(qū)內(nèi)容轉(zhuǎn)移至外設(shè)的數(shù)據(jù)寄存器中,這種多用于外設(shè)的發(fā)送通信,比如SPI、I2C和串口等。

存儲(chǔ)器到存儲(chǔ)器:就是把一個(gè)指定的存儲(chǔ)區(qū)內(nèi)容拷貝到另一個(gè)存儲(chǔ)區(qū)空間。功能類似于C語言內(nèi)存拷貝函數(shù)memcpy,不過利用DMA傳輸可以達(dá)到更高的傳輸效率。

注意:只有DMA2控制器支持存儲(chǔ)器到存儲(chǔ)器的傳輸,DMA1不支持。

DMA功能框圖

8f199c56-d60d-11ed-bfe3-dac502259ad0.png

標(biāo)號(hào)1處是外設(shè)通道,每一個(gè)數(shù)據(jù)流(標(biāo)號(hào)2)對(duì)應(yīng)著8個(gè)外設(shè)通道,外設(shè)通道選擇要解決的主要問題是決定哪一個(gè)外設(shè)作為該數(shù)據(jù)流的源地址或者目標(biāo)地址。DMA1各個(gè)通道的請(qǐng)求映像如下表所示:

8f63b1c4-d60d-11ed-bfe3-dac502259ad0.png

DMA2各個(gè)通道的請(qǐng)求映像如下表所示:

8f9424a8-d60d-11ed-bfe3-dac502259ad0.png

比如我們利用DMA將存儲(chǔ)器數(shù)據(jù)傳輸?shù)酱?,然后發(fā)送出去,那么根據(jù)上表可知,我們可以選擇DMA1的數(shù)據(jù)流3通道4,或者DMA1的數(shù)據(jù)流4通道7。而將串口3的數(shù)據(jù)傳輸?shù)酱鎯?chǔ)器則可以選擇DMA1的數(shù)據(jù)流1通道4。

標(biāo)號(hào)2處是數(shù)據(jù)流和仲裁器,一個(gè)DMA控制器對(duì)應(yīng)8個(gè)數(shù)據(jù)流,數(shù)據(jù)流包含要傳輸數(shù)據(jù)的源地址、目標(biāo)地址、數(shù)據(jù)等等信息。如果我們需要同時(shí)使用同一個(gè)DMA控制器 (DMA1 或DMA2) 多個(gè)外設(shè)請(qǐng)求時(shí),那必然需要同時(shí)使用多個(gè)數(shù)據(jù)流,這時(shí)就需要仲裁器對(duì)每一個(gè)數(shù)據(jù)流的優(yōu)先級(jí)進(jìn)行劃分。數(shù)據(jù)流的優(yōu)先級(jí)可以通過配置DMA_SxCR寄存器 PL[1:0]位,可以設(shè)置為非常高、高、中和 低四個(gè)級(jí)別。如果兩個(gè)或以上數(shù)據(jù)流軟件設(shè)置優(yōu)先級(jí)一樣,則他們優(yōu)先級(jí)取決于數(shù)據(jù)流編號(hào),編號(hào)越低越具有優(yōu)先權(quán),比如數(shù)據(jù)流2優(yōu)先級(jí)高于數(shù)據(jù)流 3。

標(biāo)號(hào)3處是FIFO,用于在源數(shù)據(jù)傳輸?shù)侥繕?biāo)地址之前臨時(shí)存放數(shù)據(jù)用的??梢酝ㄟ^DMA數(shù)據(jù)流xFIFO控制寄存器DMA_SxFCR的FTH[1:0]位來控制FIFO的閾值,分別為1/4、1/2、3/4和滿。如果數(shù)據(jù)存儲(chǔ)量達(dá)到閾值級(jí)別時(shí),F(xiàn)IFO內(nèi)容將傳輸?shù)侥繕?biāo)中。

標(biāo)號(hào)4和5處是存儲(chǔ)器端口、外設(shè)端口。DMA控制器通過存儲(chǔ)器端口和外設(shè)端口與存儲(chǔ)器和外設(shè)進(jìn)行數(shù)據(jù)傳輸。DMA2(DMA控制器2)的存儲(chǔ)器端口和外設(shè)端口都是連接到AHB總線矩陣,可以使用AHB總線矩陣功能。而DMA1的存儲(chǔ)區(qū)端口相比DMA2的要減少AHB2外設(shè)的訪問權(quán),同時(shí)DMA1外設(shè)端口是沒有連接至總線矩陣的,只有連接到APB1外設(shè),所以 DMA1不能實(shí)現(xiàn)存儲(chǔ)器到存儲(chǔ)器傳輸。

標(biāo)號(hào)6處是編程端口,AHB從器件編程端口是連接至AHB2外設(shè)的,AHB2外設(shè)在使用 DMA傳輸時(shí)需要相關(guān)控制信號(hào)。

DMA軟件配置

在標(biāo)準(zhǔn)庫函數(shù)中對(duì)DMA進(jìn)行初始化主要是對(duì)結(jié)構(gòu)體DMA_InitTypeDef內(nèi)的各類參數(shù)進(jìn)行初始化。DMA_InitTypeDef結(jié)構(gòu)體參數(shù)及介紹如下:

typedef struct
{
  uint32_t DMA_Channel;          
  uint32_t DMA_PeripheralBaseAddr; 
  uint32_t DMA_Memory0BaseAddr;   
  uint32_t DMA_DIR;               
  uint32_t DMA_BufferSize;        
  uint32_t DMA_PeripheralInc;     
  uint32_t DMA_MemoryInc;       
  uint32_t DMA_PeripheralDataSize; 
  uint32_t DMA_MemoryDataSize;    
  uint32_t DMA_Mode;             
  uint32_t DMA_Priority;          
  uint32_t DMA_FIFOMode;         
  uint32_t DMA_FIFOThreshold;     
  uint32_t DMA_MemoryBurst;     
  uint32_t DMA_PeripheralBurst;   
}DMA_InitTypeDef;

1)DMA_Channel:DMA請(qǐng)求通道的選擇,每個(gè)外設(shè)對(duì)應(yīng)固定的通道,具體設(shè)置值需要查25.2節(jié)中的DMA1和DMA2各個(gè)通道的請(qǐng)求映像表。該值在標(biāo)準(zhǔn)庫中可供選擇的參數(shù)值如下:

#define DMA_Channel_0                     ((uint32_t)0x00000000)
#define DMA_Channel_1                     ((uint32_t)0x02000000)
#define DMA_Channel_2                     ((uint32_t)0x04000000)
#define DMA_Channel_3                     ((uint32_t)0x06000000)
#define DMA_Channel_4                     ((uint32_t)0x08000000)
#define DMA_Channel_5                     ((uint32_t)0x0A000000)
#define DMA_Channel_6                     ((uint32_t)0x0C000000)
#defineDMA_Channel_7((uint32_t)0x0E000000)

2)DMA_PeripheralBaseAddr:外設(shè)地址,設(shè)定DMA_SxPAR寄存器的值;一般設(shè)置為外設(shè)的數(shù)據(jù)寄存器地址,如果是存儲(chǔ)器到存儲(chǔ)器模式則設(shè)置為其中一個(gè)存儲(chǔ)區(qū)地址。比如要進(jìn)行串口DMA傳輸,那么外設(shè)基地址為串口接收發(fā)送數(shù)據(jù)存儲(chǔ)器USART1->DR的地址,表示方法為&USART1->DR。

3)DMA_Memory0BaseAddr:存儲(chǔ)器0地址,設(shè)定DMA_SxM0AR寄存器值;一般設(shè)置為我們自定義存儲(chǔ)區(qū)的首地址。比如我們程序中自己定義的用來存放數(shù)據(jù)的數(shù)組,此時(shí)這個(gè)值設(shè)置為數(shù)組名即可。

4) DMA_DIR:傳輸方向選擇,可選外設(shè)到存儲(chǔ)器、存儲(chǔ)器到外設(shè)以及存儲(chǔ)器到存儲(chǔ)器。該值在標(biāo)準(zhǔn)庫中可供選擇的參數(shù)值如下:

DMA_DIR_PeripheralToMemory  //外設(shè)到存儲(chǔ)器
DMA_DIR_MemoryToPeripheral  //存儲(chǔ)器到外設(shè)
DMA_DIR_MemoryToMemory  //存儲(chǔ)器到存儲(chǔ)器

5)DMA_Bu?erSize:設(shè)定待傳輸數(shù)據(jù)數(shù)目,初始化設(shè)定DMA_SxNDTR寄存器的值。

6)DMA_PeripheralInc:是否使能外設(shè)地址自動(dòng)遞增功能,它設(shè)定DMA_SxCR寄存器的PINC位的值;一般外設(shè)都是只有一個(gè)數(shù)據(jù)寄存器,所以一般不會(huì)使能該位。該值在標(biāo)準(zhǔn)庫中可供選擇的參數(shù)值如下:

DMA_PeripheralInc_Enable      //使能
DMA_PeripheralInc_Disable     //不使能

7)DMA_MemoryInc:是否使能存儲(chǔ)器地址自動(dòng)遞增功能,它設(shè)定DMA_SxCR寄存器的MINC位的值;我們自定義的存儲(chǔ)區(qū)一般都是存放多個(gè)數(shù)據(jù)的,所以一般是使能存儲(chǔ)器地址自動(dòng)遞增功能。該值在標(biāo)準(zhǔn)庫中可供選擇的參數(shù)值如下:

DMA_MemoryInc_Enable      //使能
DMA_MemoryInc_Disable     //不使能

8)DMA_PeripheralDataSize:外設(shè)數(shù)據(jù)寬度,可選字節(jié)(8位)、半字(16位)和字(32位),根據(jù)外設(shè)數(shù)據(jù)長度進(jìn)行選擇。該值在標(biāo)準(zhǔn)庫中可供選擇的參數(shù)值如下:

DMA_PeripheralDataSize_Byte      //字節(jié)
DMA_PeripheralDataSize_HalfWord  //半字
DMA_PeripheralDataSize_Word     //字

9) DMA_MemoryDataSize:存儲(chǔ)器數(shù)據(jù)寬度,可選字節(jié)(8位)、半字(16位)和字(32位),和外設(shè)數(shù)據(jù)寬度相對(duì)應(yīng)。該值在標(biāo)準(zhǔn)庫中可供選擇的參數(shù)值如下:

DMA_MemoryDataSize_Byte      //字節(jié)
DMA_MemoryDataSize_HalfWord  //半字
DMA_MemoryDataSize_Word     //字

10) DMA_Mode:DMA傳輸模式選擇,可選一次傳輸或者循環(huán)傳輸。該值在標(biāo)準(zhǔn)庫中可供選擇的參數(shù)值如下:

DMA_Mode_Normal      //一次傳輸
DMA_Mode_Circular     //循環(huán)傳輸

11) DMA_Priority:軟件設(shè)置數(shù)據(jù)流的優(yōu)先級(jí),有4個(gè)可選優(yōu)先級(jí)分別為非常高、高、中和低。DMA優(yōu)先級(jí)只有在多個(gè)DMA數(shù)據(jù)流同時(shí)使用時(shí)才有意義,如果只有一個(gè)數(shù)據(jù)流的話,設(shè)置成非常高優(yōu)先級(jí)就可以了。該值在標(biāo)準(zhǔn)庫中可供選擇的參數(shù)值如下:

DMA_Priority_Low         //低
DMA_Priority_Medium     //中
DMA_Priority_High       //高
DMA_Priority_VeryHigh   //非常高

12) DMA_FIFOMode:FIFO模式使能,如果設(shè)置為DMA_FIFOMode_Enable 表示使能FIFO模式功能;如果采用直接傳輸模式,則不需要使用FIFO模式。直接模式下,DMA直接進(jìn)行數(shù)據(jù)從源地址到目的地址的傳輸。而FIFO模式下,可以將要傳輸?shù)亩鄠€(gè)數(shù)據(jù)(或字節(jié))累計(jì)存儲(chǔ)在FIFO緩沖器中,然后在FIFO緩沖器中設(shè)置存儲(chǔ)閾值,當(dāng)?shù)竭_(dá)閾值時(shí),F(xiàn)IFO會(huì)自動(dòng)把所有存儲(chǔ)的數(shù)據(jù)一次性的發(fā)送到目標(biāo)地址。該值在標(biāo)準(zhǔn)庫中可供選擇的參數(shù)值如下:

DMA_FIFOMode_Disable  //不使能
DMA_FIFOMode_Enable  //使能

13) DMA_FIFOThreshold:FIFO閾值選擇,可選4種狀態(tài)分別為FIFO容量的1/4、1/2、3/4和滿;不使用FIFO模式時(shí),該設(shè)置改值無效。該值在標(biāo)準(zhǔn)庫中可供選擇的參數(shù)值如下:

DMA_FIFOThreshold_1QuarterFull         //1/4
DMA_FIFOThreshold_HalfFull            //1/2
DMA_FIFOThreshold_3QuartersFull       //3/4
DMA_FIFOThreshold_Full              //滿

14) DMA_MemoryBurst:存儲(chǔ)器突發(fā)模式選擇,可選單次模式、4節(jié)拍的增量突發(fā)模式、8節(jié)拍的增量突發(fā)模式或16節(jié)拍的增量突發(fā)模式。單次傳輸模式下,一次操作(軟件)只能傳輸一次,突發(fā)傳輸模式下,一次操作可以傳輸多次,如4次,8次,16次。該值在標(biāo)準(zhǔn)庫中可供選擇的參數(shù)值如下:

DMA_MemoryBurst_Single            //單次
DMA_MemoryBurst_INC4            //4節(jié)拍
DMA_MemoryBurst_INC8           //8節(jié)拍
DMA_MemoryBurst_INC16          //16節(jié)拍

15) DMA_PeripheralBurst:外設(shè)突發(fā)模式選擇,可選單次模式、4節(jié)拍的增量突發(fā)模式、8節(jié)拍的增量突發(fā)模式或16節(jié)拍的增量突發(fā)模式。該值在標(biāo)準(zhǔn)庫中可供選擇的參數(shù)值如下:

DMA_PeripheralBurst_Single        //單次
DMA_PeripheralBurst_INC4         //4節(jié)拍
DMA_PeripheralBurst_INC8         //8節(jié)拍
DMA_PeripheralBurst_INC16        //16節(jié)拍

串口DMA接發(fā)通信實(shí)驗(yàn)

串口的DMA接發(fā)通信實(shí)驗(yàn)是存儲(chǔ)器到外設(shè)和外設(shè)到存儲(chǔ)器的數(shù)據(jù)傳輸。在第24課串口通信的基礎(chǔ)上編寫而成。

1.編程要點(diǎn)

1)配置USART通信功能;

2)配置DMA通信功能,存儲(chǔ)器到外設(shè)和外設(shè)到存儲(chǔ)器兩種模式的配置。

3)使能指定的DMA數(shù)據(jù)流中斷;

4)使能USART3的DMA發(fā)送和接收請(qǐng)求;

5)開始一次DMA傳輸。

2.代碼分析

代碼中有關(guān)串口的配置的程序在第24課已經(jīng)詳細(xì)講過了,這里就不再講述。主要是對(duì)DMA相關(guān)的代碼進(jìn)行分析,相關(guān)程序在dma.c文件里。

代碼清單1:DMA初始化配置

void MYDMA_Config(void)
{ 
  DMA_InitTypeDef  DMA_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);
  while (DMA_GetCmdStatus(DMA1_Stream3) != DISABLE){} 
  //存儲(chǔ)器到外設(shè)的DMA配置
  DMA_DeInit(DMA1_Stream3);
  DMA_InitStructure.DMA_Channel = DMA_Channel_4;  //通道選擇
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART3->DR);//DMA外設(shè)地址
  DMA_InitStructure.DMA_Memory0BaseAddr =(uint32_t)USART3_TX_BUF;//DMA 存儲(chǔ)器0地址
  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;//存儲(chǔ)器到外設(shè)模式
  DMA_InitStructure.DMA_BufferSize = USART3_MAX_TX_LEN;//數(shù)據(jù)傳輸量 
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外設(shè)非增量模式
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存儲(chǔ)器增量模式
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外設(shè)數(shù)據(jù)長度:8位
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//存儲(chǔ)器數(shù)據(jù)長度:8位
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;// 使用普通模式 
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;//高優(yōu)先級(jí)
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//存儲(chǔ)器突發(fā)單次傳輸
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//外設(shè)突發(fā)單次傳輸
  DMA_Init(DMA1_Stream3, &DMA_InitStructure);//初始化DMA Stream
  DMA_ClearITPendingBit(DMA1_Stream3,DMA_IT_TCIF3);                         //清除標(biāo)志位    
DMA_Cmd(DMA1_Stream3,DISABLE);//關(guān)閉DMA
DMA_ITConfig(DMA1_Stream3,DMA_IT_TC,ENABLE);
  NVIC_InitStructure.NVIC_IRQChannel                   = DMA1_Stream3_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
  USART_DMACmd(USART3,USART_DMAReq_Tx,ENABLE);     
  //外設(shè)到存儲(chǔ)器的DMA配置
  DMA_DeInit(DMA1_Stream1);
  while (DMA_GetCmdStatus(DMA1_Stream1) != DISABLE){}//等待DMA可配置 
  DMA_InitStructure.DMA_Channel = DMA_Channel_4;  //通道選擇
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART3->DR);;//DMA外設(shè)地址
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)USART3_RX_BUF;//DMA 存儲(chǔ)器0地址
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;//存儲(chǔ)器到外設(shè)模式
  DMA_InitStructure.DMA_BufferSize = USART3_MAX_RX_LEN;//數(shù)據(jù)傳輸量 
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外設(shè)非增量模式
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存儲(chǔ)器增量模式
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外設(shè)數(shù)據(jù)長度:8位
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//存儲(chǔ)器數(shù)據(jù)長度:8位
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;// 使用普通模式 
  DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;//最高優(yōu)先級(jí)
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//存儲(chǔ)器突發(fā)單次傳輸
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//外設(shè)突發(fā)單次傳輸
  DMA_Init(DMA1_Stream1, &DMA_InitStructure);//初始化DMA Stream
  DMA_ClearITPendingBit(DMA1_Stream1,DMA_IT_TCIF1);                         //清除標(biāo)志位    
DMA_Cmd(DMA1_Stream1,ENABLE);//關(guān)閉DMA
DMA_ITConfig(DMA1_Stream1,DMA_IT_TC,ENABLE);//使能DMA1數(shù)據(jù)流1的傳輸完成中斷
  NVIC_InitStructure.NVIC_IRQChannel                   = DMA1_Stream1_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
  USART_DMACmd(USART3,USART_DMAReq_Rx,ENABLE);     
}

這段代碼主要是根據(jù)第25.3節(jié)中講解的內(nèi)容對(duì)DMA進(jìn)行配置的。串口發(fā)送數(shù)據(jù)我們利用的是DMA數(shù)據(jù)流3通道4,存儲(chǔ)器是我們定義的一個(gè)數(shù)組USART3_TX_BUF,外設(shè)是串口的數(shù)據(jù)寄存器USART_DR,表示方法為&USART3->DR。串口接收數(shù)據(jù)我們利用的是DMA數(shù)據(jù)流1通道4,存儲(chǔ)器是我們定義的一個(gè)數(shù)組USART3_RX_BUF,外設(shè)是串口的數(shù)據(jù)寄存器USART_DR,表示方法為&USART3->DR。

代碼清單2:DMA1_Stream3_IRQHandler函數(shù)

void DMA1_Stream3_IRQHandler(void)  //DMA發(fā)送數(shù)據(jù)流中斷服務(wù)函數(shù)
{
    if(DMA_GetITStatus(DMA1_Stream3,DMA_IT_TCIF3) != RESET)   
    {  
        DMA_ClearITPendingBit(DMA1_Stream3,DMA_IT_TCIF3); 
        DMA_Cmd(DMA1_Stream3,DISABLE); //關(guān)閉DMA  
        USART3_DMA_Tx_flag = 0; //發(fā)送完成
    }       
}

該函數(shù)是DMA1數(shù)據(jù)流3中斷服務(wù)函數(shù),在函數(shù)里我們通過對(duì)DMA_IT_TCIF3標(biāo)志位的判斷,可以知道數(shù)據(jù)流3的數(shù)據(jù)是否傳輸完成,然后清除相應(yīng)的標(biāo)志位和關(guān)閉DMA傳輸。

代碼清單3:DMA1_Stream1_IRQHandler函數(shù)

void DMA1_Stream1_IRQHandler(void) //DMA接收數(shù)據(jù)流中斷服務(wù)函數(shù)
{
    if(DMA_GetITStatus(DMA1_Stream1,DMA_IT_TCIF1) != RESET)   
    {  
        DMA_ClearITPendingBit(DMA1_Stream1,DMA_IT_TCIF1); //清除標(biāo)志位    
        DMA_Cmd(DMA1_Stream1,DISABLE); //關(guān)閉DMA  
    }   
}

該函數(shù)的功能和DMA1數(shù)據(jù)流3中斷服務(wù)函數(shù)的功能是一樣的。

代碼清單4:USART3_IRQHandler函數(shù)

void USART3_IRQHandler(void)                  
{
   if(USART_GetITStatus(USART3 , USART_IT_IDLE) != RESET) 
    {
    USART_ReceiveData(USART3);//清除空閑中斷標(biāo)志
    DMA_Cmd(DMA1_Stream1,DISABLE);//關(guān)閉DMA ,防止干擾  
    USART3_RX_STA = USART3_MAX_RX_LEN - DMA_GetCurrDataCounter(DMA1_Stream1);//獲得接收到的字節(jié)數(shù)
      DMA_SetCurrDataCounter(DMA1_Stream1,USART3_MAX_RX_LEN);
     DMA_ClearITPendingBit(DMA1_Stream1,DMA_IT_TCIF1);//比f103多的一句  
       DMA_Cmd(DMA1_Stream1,ENABLE);// DMA 開啟,等待數(shù)據(jù)。
    USART3_RX_BUF[USART3_RX_STA&0X7FFF]='?';
    USART3_RX_STA|=0x8000;   //最高位置1,標(biāo)記接收完成了                                                                                               
    }
  if(USART_GetFlagStatus(USART3,USART_FLAG_ORE) == SET)  // 檢查 ORE 標(biāo)志,防止開關(guān)總中斷死機(jī),放在接收中斷前面
  {
    USART_ClearFlag(USART3,USART_FLAG_ORE);
    USART_ReceiveData(USART3);
  }
}

該函數(shù)是串口3的中斷服務(wù)函數(shù)。在函數(shù)里判斷接收完成是通過串口空閑中斷的方式實(shí)現(xiàn),即當(dāng)串口數(shù)據(jù)流停止后,就會(huì)產(chǎn)生IDLE中斷。然后在中斷里依次做了以下事情:處理接收buff的數(shù)據(jù);關(guān)閉串口接收DMA通道,防止后面接收到數(shù)據(jù)產(chǎn)生串?dāng)_;計(jì)算接收到的字節(jié)數(shù)存儲(chǔ)在USART3_RX_STA變量中;重新設(shè)置DMA下次要接收的數(shù)據(jù)字節(jié)數(shù);清除DMA1數(shù)據(jù)流1接收完成標(biāo)志位;開啟DMA通道,等待下一次的數(shù)據(jù)接收;置位標(biāo)志位USART3_RX_STA,表示接收完成了。同時(shí)為了防止串口溢出錯(cuò)誤,程序卡死在串口中斷里,在中斷服務(wù)函數(shù)里增加了溢出錯(cuò)誤的處理。

代碼清單5:主函數(shù)

int main(void)
{
  GPIO_Configuration();
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//設(shè)置系統(tǒng)中斷優(yōu)先級(jí)分組2
  USART_Configuration();
  printf("start
");
  while (1)
  {
    if(USART3_RX_STA&0x8000)
    {  
      //printf("USART3_Read:%s",USART3_RX_BUF);
      printf("USART3_Read:%s",USART3_RX_BUF);
      USART3_RX_STA=0;
      memset(USART3_RX_BUF,0,sizeof(USART3_RX_BUF));
    }
  }
}

主函數(shù)的編寫邏輯比較簡單,首先是各類外設(shè)的初始化,包括GPIO初始化、NVIC中斷初始化、串口初始化。然后在while循環(huán)里等待接收完成標(biāo)志置位,將接收到的數(shù)據(jù)再發(fā)送到串口調(diào)試助手,并利用memset函數(shù)將存儲(chǔ)數(shù)據(jù)的數(shù)組USART3_RX_BUF清零。

審核編輯:湯梓紅
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 控制器
    +關(guān)注

    關(guān)注

    114

    文章

    16838

    瀏覽量

    182253
  • 存儲(chǔ)器
    +關(guān)注

    關(guān)注

    38

    文章

    7613

    瀏覽量

    165913
  • adc
    adc
    +關(guān)注

    關(guān)注

    99

    文章

    6611

    瀏覽量

    547731
  • 串口
    +關(guān)注

    關(guān)注

    14

    文章

    1580

    瀏覽量

    78334
  • dma
    dma
    +關(guān)注

    關(guān)注

    3

    文章

    569

    瀏覽量

    102041

原文標(biāo)題:MCU微課堂 | CKS32F4xx系列產(chǎn)品串口DMA傳輸

文章出處:【微信號(hào):中科芯MCU,微信公眾號(hào):中科芯MCU】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    MCU微課堂|CKS32F4xx系列產(chǎn)品時(shí)鐘配置

    作為MCU運(yùn)行的基礎(chǔ),時(shí)鐘是單片機(jī)各個(gè)模塊工作時(shí)序的最小時(shí)間單位,推動(dòng)單片機(jī)的各指令執(zhí)行,是MCU選型的一個(gè)重要指標(biāo)。CKS32F4xx系列產(chǎn)品具有眾多的外設(shè),但并非所有的外設(shè)均需要系統(tǒng)時(shí)鐘的高頻率
    發(fā)表于 12-12 10:17 ?963次閱讀

    CKS32F4xx系列ETH通信詳解

    CKS32F4xx系列芯片自帶以太網(wǎng)模塊,該模塊包括帶專用DMA控制器的MAC 802.3(介質(zhì)訪問控制)控制器
    的頭像 發(fā)表于 11-10 11:13 ?1264次閱讀
    <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列</b>ETH通信詳解

    CKS32F4xx系列產(chǎn)品NVIC中斷優(yōu)先級(jí)管理單元講解

    本課將為大家講解CKS32F4xx系列產(chǎn)品的中斷優(yōu)先級(jí)管理單元NVIC。CM4內(nèi)核共支持256個(gè)中斷,其中包含了16個(gè)內(nèi)核中斷和240個(gè)外部中斷,具有256級(jí)可編程中斷設(shè)置。但CKS32F4x
    的頭像 發(fā)表于 02-06 14:52 ?1414次閱讀

    CKS32F4xx系列產(chǎn)品的定時(shí)器使用-基本特征和定時(shí)操作

    這一課我們將介紹CKS32F4XX系列產(chǎn)品的定時(shí)器使用,CKS32F4XX的定時(shí)器功能十分強(qiáng)大,包含2個(gè)高級(jí)控制定時(shí)器,8個(gè)普通定時(shí)器,2個(gè)基礎(chǔ)定時(shí)器,以及兩個(gè)看門狗定時(shí)器和一個(gè)系統(tǒng)定時(shí)器,總共15個(gè)定時(shí)器之多。關(guān)于定時(shí)器部分內(nèi)
    的頭像 發(fā)表于 05-19 09:18 ?1119次閱讀
    <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列產(chǎn)品</b>的定時(shí)器使用-基本特征和定時(shí)操作

    CKS32F4xx系列RNG功能設(shè)置

    ? MCU 微課堂 CKS32F4xx 系 列RNG功能 隨機(jī)數(shù)發(fā)生器簡介 ? ? CKS32F4xx系列自帶了硬件隨機(jī)數(shù)發(fā)生器(RNG),RNG處理器是一個(gè)以連續(xù)模擬噪聲為基礎(chǔ)的隨機(jī)數(shù)發(fā)生器,在
    的頭像 發(fā)表于 09-08 10:01 ?798次閱讀
    <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列</b>RNG功能設(shè)置

    CKS32F4xx系列DAC功能

    CKS32F4xx系列DAC功能
    的頭像 發(fā)表于 11-06 16:56 ?1040次閱讀
    <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列</b>DAC功能

    CKS32F4xx系列ADC多通道DMA電壓采集

    CKS32F4xx系列ADC多通道DMA電壓采集
    的頭像 發(fā)表于 11-06 16:53 ?1278次閱讀

    CKS32F4xx系列低功耗模式SLEEP模式

    CKS32F4xx系列低功耗模式SLEEP模式
    的頭像 發(fā)表于 11-06 16:59 ?867次閱讀
    <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列</b>低功耗模式SLEEP模式

    CKS32F4xx系列低功耗模式STOP模式

    CKS32F4xx系列低功耗模式STOP模式
    的頭像 發(fā)表于 11-06 17:08 ?778次閱讀
    <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列</b>低功耗模式STOP模式

    CKS32F4xx系列產(chǎn)品Timer的基本使用方法-定時(shí)器脈沖計(jì)數(shù)

    CKS32F4xx系列產(chǎn)品Timer的基本使用方法-定時(shí)器脈沖計(jì)數(shù)
    的頭像 發(fā)表于 11-09 17:38 ?1301次閱讀
    <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列產(chǎn)品</b>Timer的基本使用方法-定時(shí)器脈沖計(jì)數(shù)

    CKS32F4xx系列產(chǎn)品Timer的基本使用方法-比較輸出

    CKS32F4xx系列產(chǎn)品Timer的基本使用方法-比較輸出
    的頭像 發(fā)表于 11-09 17:39 ?1043次閱讀
    <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列產(chǎn)品</b>Timer的基本使用方法-比較輸出

    CKS32F4xx系列產(chǎn)品Timer的基本使用方法-定時(shí)操作

    CKS32F4xx系列產(chǎn)品Timer的基本使用方法-定時(shí)操作
    的頭像 發(fā)表于 11-09 17:41 ?768次閱讀
    <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列產(chǎn)品</b>Timer的基本使用方法-定時(shí)操作

    MCU微課堂 | CKS32F4xx系列產(chǎn)品SPI通信

    MCU微課堂 | CKS32F4xx系列產(chǎn)品SPI通信
    的頭像 發(fā)表于 10-24 17:12 ?910次閱讀
    MCU微課堂 | <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列產(chǎn)品</b>SPI通信

    MCU微課堂 | CKS32F4xx系列產(chǎn)品GPIO口配置

    MCU微課堂 | CKS32F4xx系列產(chǎn)品GPIO口配置
    的頭像 發(fā)表于 10-24 15:14 ?1000次閱讀
    MCU微課堂 | <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列產(chǎn)品</b>GPIO口配置

    CKS32F4xx系列FSMC功能簡介

    本課講為大家講解CKS32F4xx系列產(chǎn)品的FSMC應(yīng)用實(shí)例,F(xiàn)SMC全稱是Flexible Static Memory Controller,讀作靈活的靜態(tài)存儲(chǔ)控制器,顧名思義,MCU可以通過FSMC擴(kuò)展靜態(tài)內(nèi)存
    的頭像 發(fā)表于 04-14 15:06 ?1304次閱讀
    <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列</b>FSMC功能簡介