1.DMA簡介
直接存儲器存取(DMA)用來提供在外設和存儲器之間或者存儲器和存儲器之間的高速數據傳輸。無須CPU干預,數據可以通過DMA快速地移動,這就節(jié)省了CPU的資源來做其他操作。
STM32F10x中有兩個DMA控制器(DMA1有7個通道,DMA2有5個通道)每個通道專門用來管理來自于一個或多個外設對存儲器訪問的請求。還有一個仲裁器來協調各個DMA請求的優(yōu)先權。
DMA1請求映像
??USART1_TX – DMA1_Chnanel4
??USART1_RC – DMA1_Channel5
??利用DMA功能完成串口數據處理,無需CPU干預,減少CPU占用。
2.程序設計
?1.DMA1_CH4配置
/******DMA配合串口1發(fā)送數據************
**形參:u32 cpar -- 外設地址
**
**例:DMA_CH4_Init(&USART1->DR,buff)
**外設地址:USART1->DR的地址
** buff的地址
**************************************/
void DMA_CH4_Init(u32 cpar)
{
RCC->AHBENR|=1<<0;//dma1時鐘使能
DMA1_Channel4->CCR&=~(1<<14);//非存儲器到存儲器模式
DMA1_Channel4->CCR|=0x3<<12;//設置CH4優(yōu)先級為最高
DMA1_Channel4->CCR&=~(0x3<<10);//存儲器數據寬度8位
DMA1_Channel4->CCR&=~(0x3<<8);//外設數據寬度8位
DMA1_Channel4->CCR|=1<<7;//存儲器地址增量
DMA1_Channel4->CCR&=~(1<<6);//外設地址不增量
DMA1_Channel4->CCR&=~(1<<5);//不執(zhí)行循環(huán)操作
DMA1_Channel4->CCR|=1<<4;//從存儲器讀
DMA1_Channel4->CPAR=cpar;//外設地址
}
/**********開啟DMA1_CH4數據傳輸*************
***
***形參:u16 data_len -- DMA要傳輸數目
***********************************************/
void DMA_CH4_Start(u8 *buff,u16 data_len)
{
DMA1_Channel4->CMAR=(u32)buff;//存儲器地址
DMA1_Channel4->CCR&=~(1<<0);//關閉通道傳輸
DMA1_Channel4->CNDTR=data_len;//設置傳輸數量
DMA1_Channel4->CCR|=1<<0;//開啟通道傳輸
}
??2.DMA1_CH5配置
/******DMA配合串口1接收數據************
**形參:u32 cpar -- 外設地址
** u32 cmar -- 存儲器地址
**
**例:DMA_CH5_Init(&USART1->DR,buff)
**外設地址:USART1->DR的地址
** buff的地址
**************************************/
void DMA_CH5_Init(u32 cpar,u32 cmar)
{
RCC->AHBENR|=1<<0;//dma1時鐘使能
DMA1_Channel5->CCR&=~(1<<14);//非存儲器到存儲器模式
DMA1_Channel5->CCR|=0x3<<12;//設置CH4優(yōu)先級為最高
DMA1_Channel5->CCR&=~(0x3<<10);//存儲器數據寬度8位
DMA1_Channel5->CCR&=~(0x3<<8);//外設數據寬度8位
DMA1_Channel5->CCR|=1<<7;//存儲器地址增量
DMA1_Channel5->CCR&=~(1<<6);//外設地址不增量
DMA1_Channel5->CCR&=~(1<<5);//執(zhí)行循環(huán)操作
DMA1_Channel5->CCR&=~(1<<4);//從外設讀
DMA1_Channel5->CPAR=cpar;//外設地址
DMA1_Channel5->CMAR=cmar;//存儲器地址
DMA1_Channel5->CCR&=~(1<<0);//關閉通道傳輸
DMA1_Channel5->CNDTR=1024;//設置傳輸數量
DMA1_Channel5->CCR|=1<<0;//開啟通道傳輸
}
??3.USART1配置
/********************串口初始化函數封裝*********************
****硬件接口:USART1_TX -- PA9(發(fā)送)
** USART1-RX --PA10(接收)
** USART2_TX -- PA2(發(fā)送)
** USART2-RX --PA3(接收)
** USART3_TX -- PB10(發(fā)送)
** USART3_RX -- PB11(接收)
形參:USART_TypeDef *USARTx -- 要配置的哪個串口
** u32 baud --波特率
** u32 sysclk --時鐘頻率(USART1 --72MHZ ,USAT2USART3 --36MHZ)
**
***********************************************************/
void Usartx_Init(USART_TypeDef *USARTx,u32 baud,u32 sysclk)
{
if(USART1 == USARTx)
{
/*1.開時鐘*/
RCC->APB2ENR|=1<<2;//PA時鐘
RCC->APB2ENR|=1<<14;//串口時鐘
RCC->APB2RSTR|=1<<14;//串口復位
RCC->APB2RSTR&=~(1<<14);//取消復位
/*2.配置GPIO口*/
GPIOA->CRH&=0xFFFFF00F;
GPIOA->CRH|=0x000008B0;//上下拉輸入,復用推挽輸出
USART1->CR3|=1<<7;//DMA發(fā)送
USART1->CR3|=1<<6;//DMA接收
USART1->CR1|=1<<4;//IDLE(空閑幀中斷)
STM32_NVIC_SetPriority(USART1_IRQn,0,1);//設置優(yōu)先級
}
else if(USART2 == USARTx)
{
/*1.開時鐘*/
RCC->APB2ENR|=1<<2;//PA時鐘
RCC->APB1ENR|=1<<17;//USART2時鐘
RCC->APB1RSTR|=1<<17;//開復位時鐘
RCC->APB1RSTR&=~(1<<17);//取消復位
/*2.配置GPIO口*/
GPIOA->CRL&=0xFFFF00FF;//清除原來寄存器中的值
GPIOA->CRL|=0x00008B00;
#ifdef USART2_IRQ
USART2->CR1|=1<<5;//串口2接收中斷
STM32_NVIC_SetPriority(USART2_IRQn,1,2);//設置優(yōu)先級
#endif
}
else if(USART3 == USARTx)
{
/*1.開時鐘*/
RCC->APB2ENR|=1<<3;//PB時鐘
RCC->APB1ENR|=1<<18;//USART3時鐘
RCC->APB1RSTR|=1<<18;//開復位時鐘
RCC->APB1RSTR&=~(1<<18);//取消復位
/*2.配置GPIO口*/
GPIOB->CRH&=0xFFFF00FF;
GPIOB->CRH|=0x00008B00;
#ifdef USART3_IRQ
USART3->CR1|=1<<5;//開啟接收中斷
STM32_NVIC_SetPriority(USART3_IRQn,0,0);//設置優(yōu)先級
#endif
}
else return;
/*3.配置串口核心寄存器*/
USARTx->BRR=sysclk*1000000/baud;//設置波特率
USARTx->CR1|=1<<2;//接收使能
USARTx->CR1|=1<<3;//發(fā)送使能
USARTx->CR1|=1<<13;//使能串口3
#ifdef DMA_USART1_SEND //利用DMA完成數據收發(fā)
DMA_CH5_Init((u32 )&USART1->DR,(u32 )usart1_rx_buff);//DMA配合串口1接收數據
DMA_CH4_Init((u32 )&USART1->DR);
#endif
}
4.串口1中斷,DMA數據接收數據
u8 usart1_rx_buff[1024];//串口1接收數據緩沖區(qū)
u16 usart1_cnt=0;//保存數組下班
u8 usart1_flag;//接收完成標志符
void USART1_IRQHandler(void)
{
U8 C;
//清除標志:先讀USART_SR,再讀USART_DR
if(USART1->SR&1<<4)//空閑幀
{
C=USART1->DR;
C=c;
// USART1->DR=c;
Usart1_Receive_Data();//接收數據處理函數
}
USART1->SR=0;//清除標志位
}
/*************************串口接收數據函數********************/
void Usart1_Receive_Data(void)
{
DMA1_Channel5->CCR&=~(1<<0);//關閉通道傳輸
usart1_cnt=1024-DMA1_Channel5->CNDTR;//獲取接收到是字符長度
if(usart1_cnt>=1024)usart1_cnt=0;
DMA1->IFCR|=1<<17;//清除標志位
DMA1_Channel5->CNDTR=1024;//從新賦值
DMA1_Channel5->CCR|=1<<0;//開啟通道傳輸
usart1_flag=1;
}
??5.串口數據發(fā)送
/****************串口發(fā)送字符串*****************************/
void Usart1_SendStr(u8 *str)
{
#ifdef DMA_USART1_SEND
DMA_CH4_Start(str,strlen((char *)str));
#else
while(*str!='?')
{
USART1->DR=*str++;
while(!(USART1->SR&1<<7));
}
#endif
}
6.硬件初始化,DMA配合串口調試
int main()
{
u8 key;
Beep_Init();//蜂鳴器初始化
Led_Init();//LED初始化
Key_Init();//按鍵初始化
Usartx_Init(USART1,115200,72);
while(1)
{
key=Key_Scan();
if(key)
{
Usart1_SendStr((u8 *)"DMA1配合串口收發(fā)數據不定長測試234556789rn");
}
if(usart1_flag)
{
usart1_rx_buff[usart1_cnt]='?';
printf("%srn",usart1_rx_buff);
usart1_flag=0;
}
}
}
7.運行效果
-
存儲器
+關注
關注
38文章
7484瀏覽量
163760 -
STM32F10x
+關注
關注
1文章
81瀏覽量
20681 -
dma
+關注
關注
3文章
560瀏覽量
100544
發(fā)布評論請先 登錄
相關推薦
評論