1.初始化
//RCC
RCC->APB1ENR|=1<<20; //使能串口5時鍾
RCC->APB1ENR|=1<<19; //使能串口4時鍾
RCC->APB1ENR|=1<<18; //使能串口3時鍾
RCC->APB1ENR|=1<<17; //使能串口2時鍾
RCC->APB2ENR|=1<<4; //使能串口1時鍾
RCC->APB2ENR|=1<<5; //使能串口6時鍾
RCC->AHB1ENR|=1<<21;//DMA1時鍾使能
RCC->AHB1ENR|=1<<22;//DMA2時鍾使能
//GPIO
//串口6
GPIO_AF_Set(GPIOG,9,8);
GPIO_AF_Set(GPIOG,14,8);
GPIO_Set(GPIOG,PIN9|PIN14,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_50M,GPIO_PUPD_PD);//復用功能
//UART4
DMA1_Stream2->PAR=(uint32_t)&(UART4->DR); //DMA外設地址 多重ADC->CDR
DMA1_Stream2->CR=0; //先全部復位CR寄存器值
DMA1_Stream2->NDTR=50; //傳輸數據項個數
DMA1_Stream2->M0AR= (uint32_t)_rece_data1; //DMA 存儲器0地址
DMA1_Stream2->CR|=4<<25; //通道選擇4
DMA1_Stream2->CR|=0<<23; //存儲器單次傳輸
DMA1_Stream2->CR|=0<<21; //外設單次傳輸
DMA1_Stream2->CR|=1<<16; //中等優先級 2:高 3:非常高
DMA1_Stream2->CR|=0<<13; //存儲器數據大小為8位 0:8位 1:16位 2:32位
DMA1_Stream2->CR|=0<<11; //外設數據大小為8位 0:8位 1:16位 2:32位
DMA1_Stream2->CR|=1<<10; //存儲器地址遞增
DMA1_Stream2->CR|=0<<9; //外設地址固定
DMA1_Stream2->CR|=0<<8; //普通模式
DMA1_Stream2->CR|=0<<6; //0:外設到存儲器 1:存儲器到外設 2:存儲器到存儲器
DMA1_Stream2->CR|=1<<4; //開啟傳輸完成中斷
DMA1_Stream2->CR|=1<<0; //開啟DMA傳輸
MY_NVIC_Init(3,0,DMA1_Stream2_IRQn,4); //搶占1,子優先級3,組2
MY_NVIC_Init(2,0,UART4_IRQn,4); //搶占1,子優先級3,組2
//波特率為
temp=(float)(42000000)/(_baud*16);//得到USARTDIV@OVER8=0
mantissa=(u16)(temp); //得到整數部分
fraction=(u16)((temp-mantissa)*16); //得到小數部分@OVER8=0
mantissa<<=4;
mantissa+=fraction;
UART4->CR1 = 0;
UART4->CR3 = 0;
//波特率設置
UART4->BRR=mantissa; //波特率設置
UART4->CR1&=~(1<<15); //設置OVER8=0
UART4->CR1|=1<<4; //空閑中斷
UART4->CR1|=1<<3; //串口發送使能
UART4->CR1|=1<<2; //串口接收使能
UART4->CR3|=1<<6; //開啟DMA輸出
//使能
UART4->CR1|=1<<13; //串口使能
//UART5
//接收
DMA1_Stream0->PAR=(uint32_t)&(UART5->DR); //DMA外設地址 多重ADC->CDR
DMA1_Stream0->CR=0; //先全部復位CR寄存器值
DMA1_Stream0->M0AR= (uint32_t)_rece_data2; //DMA 存儲器0地址
DMA1_Stream0->NDTR=50; //傳輸數據項個數
DMA1_Stream0->CR|=4<<25; //通道選擇4
DMA1_Stream0->CR|=0<<23; //存儲器單次傳輸
DMA1_Stream0->CR|=0<<21; //外設單次傳輸
DMA1_Stream0->CR|=1<<16; //中等優先級 2:高 3:非常高
DMA1_Stream0->CR|=0<<13; //存儲器數據大小為8位 0:8位 1:16位 2:32位
DMA1_Stream0->CR|=0<<11; //外設數據大小為8位 0:8位 1:16位 2:32位
DMA1_Stream0->CR|=1<<10; //存儲器地址遞增
DMA1_Stream0->CR|=0<<9; //外設地址固定
DMA1_Stream0->CR|=0<<8; //普通模式
DMA1_Stream0->CR|=0<<6; //0:外設到存儲器 1:存儲器到外設 2:存儲器到存儲器
DMA1_Stream0->CR|=1<<4; //開啟傳輸完成中斷
DMA1_Stream0->CR|=1<<0; //開啟DMA傳輸
MY_NVIC_Init(4,0,DMA1_Stream0_IRQn,4); //搶占1,子優先級3,組2
MY_NVIC_Init(3,0,UART5_IRQn,4); //搶占1,子優先級3,組2
//發送
DMA1_Stream7->M0AR= (uint32_t)uart5_send; //DMA 存儲器0地址
DMA1_Stream7->NDTR=0; //傳輸數據項個數
DMA1_Stream7->PAR=(uint32_t)&(UART5->DR); //DMA外設地址 多重ADC->CDR
DMA1_Stream7->CR=0; //先全部復位CR寄存器值
DMA1_Stream7->CR|=4<<25; //通道選擇4
DMA1_Stream7->CR|=0<<23; //存儲器單次傳輸
DMA1_Stream7->CR|=0<<21; //外設單次傳輸
DMA1_Stream7->CR|=3<<16; //中等優先級 2:高 3:非常高
DMA1_Stream7->CR|=0<<13; //存儲器數據大小為8位 0:8位 1:16位 2:32位
DMA1_Stream7->CR|=0<<11; //外設數據大小為8位 0:8位 1:16位 2:32位
DMA1_Stream7->CR|=1<<10; //存儲器地址遞增
DMA1_Stream7->CR|=0<<9; //外設地址固定
DMA1_Stream7->CR|=0<<8; //普通模式
DMA1_Stream7->CR|=1<<6; //0:外設到存儲器 1:存儲器到外設 2:存儲器到存儲器
//波特率為
temp=(float)(42000000)/(_baud*16);//得到USARTDIV@OVER8=0
mantissa=(u16)(temp); //得到整數部分
fraction=(u16)((temp-mantissa)*16); //得到小數部分@OVER8=0
mantissa<<=4;
mantissa+=fraction;
UART5->CR1 = 0;
UART5->CR3 = 0;
//波特率設置
UART5->BRR=mantissa; //波特率設置
UART5->CR1&=~(1<<15); //設置OVER8=0
UART5->CR1|=1<<4; //空閑中斷
UART5->CR1|=1<<3; //串口發送使能
UART5->CR1|=1<<2; //串口接收使能
UART5->CR3|=1<<6; //開啟DMA接收
UART5->CR3|=1<<7; //開啟DMA發送
//使能
UART5->CR1|=1<<13; //串口使能
//USART6
DMA2_Stream1->PAR=(uint32_t)&(USART6->DR); //DMA外設地址 多重ADC->CDR
DMA2_Stream1->CR=0; //先全部復位CR寄存器值
DMA2_Stream1->M0AR= (uint32_t)_rece_data3; //DMA 存儲器0地址
DMA2_Stream1->NDTR=50; //傳輸數據項個數
DMA2_Stream1->CR|=5<<25; //通道選擇5
DMA2_Stream1->CR|=0<<23; //存儲器單次傳輸
DMA2_Stream1->CR|=0<<21; //外設單次傳輸
DMA2_Stream1->CR|=1<<16; //中等優先級 2:高 3:非常高
DMA2_Stream1->CR|=0<<13; //存儲器數據大小為8位 0:8位 1:16位 2:32位
DMA2_Stream1->CR|=0<<11; //外設數據大小為8位 0:8位 1:16位 2:32位
DMA2_Stream1->CR|=1<<10; //存儲器地址遞增
DMA2_Stream1->CR|=0<<9; //外設地址固定
DMA2_Stream1->CR|=0<<8; //普通模式
DMA2_Stream1->CR|=0<<6; //0:外設到存儲器 1:存儲器到外設 2:存儲器到存儲器
DMA2_Stream1->CR|=1<<4; //開啟傳輸完成中斷
DMA2_Stream1->CR|=1<<0; //開啟DMA傳輸
MY_NVIC_Init(5,0,DMA2_Stream1_IRQn,4); //搶占1,子優先級3,組2
MY_NVIC_Init(4,0,USART6_IRQn,4); //搶占1,子優先級3,組2
//波特率為
temp=(float)(84000000)/(_baud*16);//得到USARTDIV@OVER8=0
mantissa=(u16)(temp); //得到整數部分
fraction=(u16)((temp-mantissa)*16); //得到小數部分@OVER8=0
mantissa<<=4;
mantissa+=fraction;
USART6->CR1 = 0;
USART6->CR3 = 0;
//波特率設置
USART6->BRR=mantissa; //波特率設置
USART6->CR1&=~(1<<15); //設置OVER8=0
USART6->CR1|=1<<4; //空閑中斷
USART6->CR1|=1<<3; //串口發送使能
USART6->CR1|=1<<2; //串口接收使能
USART6->CR3|=1<<6; //開啟DMA輸出
//使能
USART6->CR1|=1<<13; //串口使能
//USART1
DMA2_Stream2->PAR=(uint32_t)&(USART1->DR); //DMA外設地址 多重ADC->CDR
DMA2_Stream2->CR=0; //先全部復位CR寄存器值
DMA2_Stream2->M0AR= (uint32_t)_rece_data4; //DMA 存儲器0地址
DMA2_Stream2->NDTR=50; //傳輸數據項個數
DMA2_Stream2->CR|=4<<25; //通道選擇4
DMA2_Stream2->CR|=0<<23; //存儲器單次傳輸
DMA2_Stream2->CR|=0<<21; //外設單次傳輸
DMA2_Stream2->CR|=1<<16; //中等優先級 2:高 3:非常高
DMA2_Stream2->CR|=0<<13; //存儲器數據大小為8位 0:8位 1:16位 2:32位
DMA2_Stream2->CR|=0<<11; //外設數據大小為8位 0:8位 1:16位 2:32位
DMA2_Stream2->CR|=1<<10; //存儲器地址遞增
DMA2_Stream2->CR|=0<<9; //外設地址固定
DMA2_Stream2->CR|=0<<8; //普通模式
DMA2_Stream2->CR|=0<<6; //0:外設到存儲器 1:存儲器到外設 2:存儲器到存儲器
DMA2_Stream2->CR|=1<<4; //開啟傳輸完成中斷
DMA2_Stream2->CR|=1<<0; //開啟DMA傳輸
MY_NVIC_Init(6,0,DMA2_Stream2_IRQn,4); //搶占1,子優先級3,組2
MY_NVIC_Init(5,0,USART1_IRQn,4); //搶占1,子優先級3,組2
//波特率為
temp=(float)(84000000)/(_baud*16);//得到USARTDIV@OVER8=0
mantissa=(u16)(temp); //得到整數部分
fraction=(u16)((temp-mantissa)*16); //得到小數部分@OVER8=0
mantissa<<=4;
mantissa+=fraction;
USART1->CR1 = 0;
USART1->CR3 = 0;
//波特率設置
USART1->BRR=mantissa; //波特率設置
USART1->CR1&=~(1<<15); //設置OVER8=0
USART1->CR1|=1<<4; //空閑中斷
USART1->CR1|=1<<3; //串口發送使能
USART1->CR1|=1<<2; //串口接收使能
USART1->CR3|=1<<6; //開啟DMA輸出
//使能
USART1->CR1|=1<<13; //串口使能
2.串口空閑中斷接收
void UART4_IRQHandler(void)
{
if( ( UART4->SR&(1<<4) ) >> 4 == 1 ) //發生空閑中斷
{
DMA1_Stream2->CR &= ~(1<<0); //關閉DMA傳輸 會發生DMA完成中斷
UART4->CR1 &= ~(1<<2); //接收關閉
UART4->SR;
UART4->DR;
}
}
void DMA1_Stream2_IRQHandler(void)
{
u8 num = 0;
if( ( DMA1->LISR&(1<<21) ) >> 21 == 1 ) //完成中斷
{
DMA1_Stream2->CR &= ~(1<<0); //關閉DMA傳輸
num = 50 - DMA1_Stream2 ->NDTR; //獲取讀到的字節數
if( usart1_nux == 0 ) //互斥量,未使用數據,可進行更改
{
for( u8 i =0; i<num; i++ )
{
_rece_temp1[i] = _rece_data1[i];
}
}
usart1_num = num;
DMA1_Stream2->NDTR = 50; //重新填充
DMA1->LIFCR |= 1<<21; //清除完成中斷標志位
DMA1_Stream2->CR |= 1<<0; //開啟DMA傳輸
UART4->CR1 |= 1<<2; //接收開啟
}
}
void UART5_IRQHandler(void)
{
if( ( UART5->SR&(1<<4) ) >> 4 == 1 ) //發生空閑中斷
{
DMA1_Stream0->CR &= ~(1<<0); //關閉DMA傳輸
UART5->CR1 &= ~(1<<2); //接收關閉
UART5->SR;
UART5->DR;
}
}
void DMA1_Stream0_IRQHandler(void)
{
u8 num = 0;
num = 50 - DMA1_Stream0 ->NDTR; //獲取讀到的字節數
if( usart2_nux == 0 )
{
for( u8 i =0; i<num; i++ )
{
_rece_temp2[i] = _rece_data2[i];
}
}
usart2_num = num;
DMA1_Stream0->NDTR = 50; //重新填充
DMA1->LIFCR |= 1<<5;
DMA1_Stream0->CR |= 1<<0; //開啟DMA傳輸
UART5->CR1 |= 1<<2; //接收開啟
}
void USART6_IRQHandler(void)
{
if( ( USART6->SR&(1<<4) ) >> 4 == 1 ) //發生空閑中斷
{
DMA2_Stream1->CR &= ~(1<<0); //關閉DMA傳輸
USART6->CR1 &= ~(1<<2); //接收關閉
USART6->SR;
USART6->DR;
}
}
void DMA2_Stream1_IRQHandler(void)
{
u8 num = 0;
num = 50 - DMA2_Stream1 ->NDTR; //獲取讀到的字節數
if( usart3_nux == 0 )
{
for( u8 i =0; i<num; i++ )
{
_rece_temp3[i] = _rece_data3[i];
}
}
usart3_num = num;
DMA2_Stream1->NDTR = 50; //重新填充
DMA2->LIFCR |= 1<<11;
DMA2_Stream1->CR |= 1<<0; //開啟DMA傳輸
USART6->CR1 |= 1<<2; //接收開啟
}
}
void USART1_IRQHandler(void)
{
if( ( USART1->SR&(1<<4) ) >> 4 == 1 ) //發生空閑中斷
{
DMA2_Stream2->CR &= ~(1<<0); //關閉DMA傳輸,此時會發生DMA完成中斷
USART1->CR1 &= ~(1<<2); //接收關閉
USART1->SR;
USART1->DR;
}
}
void DMA2_Stream2_IRQHandler(void)
{
u8 num = 0;
num = 50 - DMA2_Stream2 ->NDTR; //獲取讀到的字節數
if( usart4_nux == 0 )
{
for( u8 i =0; i<num; i++ )
{
_rece_temp4[i] = _rece_data4[i];
}
}
usart4_num = num;
DMA2_Stream2->NDTR = 50; //重新填充
DMA2->LIFCR |= 1<<21;
DMA2_Stream2->CR |= 1<<0; //開啟DMA傳輸
USART1->CR1 |= 1<<2; //接收開啟
}
//接收函數
u8 USART_RECE(u8 _sum, u8 *_rece)
{
u8 temp = 0;
if(_sum >50)
{
_sum = 50;
}
if( usart4_num == 0 )
{
return 0;
}
else
{
usart4_nux = 1; //互斥量,占用數據
for( u8 i=0; i<_sum; i++ )
{
*_rece = _rece_temp4[i];
if( i+1 > usart4_num ) //請求讀數據量超過接收數據量,后面置0
{
*_rece = 0;
}
_rece++;
}
temp = usart4_num;
usart4_nux = 0; //釋放互斥量
usart4_num = 0;
}
return temp; //返回接收到的數據個數
}
3.串口DMA發送
//發送函數
void UART5_SEND(u8 _sum, const u8 *_send){
static uint8_t send_flag = 0;
u8 *pBuf = NULL;
pBuf = uart5_send;
if( _sum > 50 )
{
_sum = 50;
}
for( u8 i=0; i<_sum; i++ )
{
*pBuf++ = *_send++;
}
if( send_flag == 0 ) //未進行過發送,直接發
{
DMA1_Stream7->NDTR=_sum; //數據傳輸量
DMA1_Stream7->CR|=1<<0; //開啟DMA傳輸
send_flag = 1;
}
else //等待發送完成后,再進行發送
{
if((DMA1->HISR & (1<<27)) >> 27==1) //DMA1_Steam7傳輸完成標志
{
DMA1_Stream7->CR&=~(1<<0); //關閉DMA
while((DMA1_Stream7->CR & (uint32_t)DMA_SxCR_EN) != 0); //確保DMA可以被設置
DMA1->HIFCR|=1<<27;//清除DMA1_Steam7傳輸完成標志,不清的話第二次不能發送
DMA1_Stream7->NDTR=_sum; //數據傳輸量
DMA1_Stream7->CR|=1<<0; //開啟DMA傳輸
}
}
}