|
1、基于RTX系统阻塞,实现串口DMA收发数据。采用当前时间片与上一时间片串口接收DMA流传输数据量相同来判断串口数据是否接收完毕。 串口DMA发送中断服务函数中开启串口发送完成中断,
__align(32) static u8 ucHmiTxBuf[MBBUFSIZE];
__align(32) static u8 ucHmiRxBuf[MBBUFSIZE];
static u16 USART2_DMAR(u8 *rbuf, u16 rlen, u16 timeout)
{
u16 c;
c = USART2->SR;
c = USART2->DR;
DMA1_Stream5->CR &= ~DMA_SxCR_EN; //禁止DMA
DMA1_Stream5->NDTR = rlen;
DMA1_Stream5->PAR = (u32)(&USART2->DR);
DMA1_Stream5->M0AR = (u32)rbuf;
DMA1_Stream5->CR = 0;
DMA1_Stream5->CR |= 4<<25 | 1<<17 | 0<<13 | 0<<11 | 1<<10 | 0<<6;
USART2->CR3 |= USART_CR3_DMAR; //使能TXDMA功能
DMA1->HIFCR = (0x000F << 8) | (0x0001 << 6);//清标志
DMA1_Stream5->CR |= DMA_SxCR_EN; //使能DMA
/*-----------------------------------------------------------
等数据进来
-------------------------------------------------------------*/
do
{
os_dly_wait(5);
if (--timeout == 0) break;
}
while (DMA1_Stream5->NDTR == rlen);
if (timeout == 0)
{
USART2->CR3 &= ~USART_CR3_DMAR;
DMA1_Stream5->CR &= ~DMA_SxCR_EN; //禁止DMA
return 0; //接收超时
}
/*-----------------------------------------------------------
等待串口数据接收完毕,返回接收数据长度
-------------------------------------------------------------*/
do
{
c = DMA1_Stream5->NDTR;
os_dly_wait(5);
}
while (c != DMA1_Stream5->NDTR);
USART2->CR3 &= ~USART_CR3_DMAR;
DMA1_Stream5->CR &= ~DMA_SxCR_EN;
return(rlen - DMA1_Stream5->NDTR);
}
static u8 USART2_DMAT(u8 *sbuf, u16 slen)
{
DMA1_Stream6->CR &= ~DMA_SxCR_EN;
DMA1_Stream6->NDTR = slen;
DMA1_Stream6->PAR = (u32)(&USART2->DR);
DMA1_Stream6->M0AR = (u32)sbuf;
DMA1_Stream6->CR = 4<<25 | 1<<17 | 0<<13 | 0<<11 | 1<<10 | 1<<6 | 1<<4;
USART2->CR3 |= USART_CR3_DMAT;
DMA1->HIFCR |= (0x000F << 18) | (0x0001 << 16);
MY_NVIC_Init(7,0,DMA1_Stream6_IRQn,4);
DMA1_Stream6->CR |= DMA_SxCR_EN;
return 1;
}
void USART2_IRQHandler(void)
{
if(USART2->SR & USART_SR_TC)
{
USART2->CR3 &= ~USART_CR3_DMAT;
USART2->SR &= ~USART_SR_TC;
USART2->CR1 &= ~USART_CR1_TCIE;
HMI485RCV();
}
}
void DMA1_Stream6_IRQHandler(void)
{
if(DMA1->HISR & DMA_HISR_TCIF6)
{
DMA1_Stream6->CR &= ~DMA_SxCR_EN;
DMA1->HIFCR |= DMA_HIFCR_CTCIF6;
USART2->CR1 |= USART_CR1_TCIE;
}
}
int initUsart2(u32 pclk1,u32 bound,u16 stopbits,u16 parity)
{
float temp;
u16 mantissa;
u16 fraction;
if(pclk1 > 42)
pclk1 = 42;
temp=(float)(pclk1*1000000)/(bound*16);//得到USARTDIV@OVER8=0
mantissa=temp; //得到整数部分
fraction=(temp-mantissa)*16; //得到小数部分@OVER8=0
mantissa<<=4;
mantissa+=fraction;
RCC->APB1RSTR |= RCC_APB1RSTR_USART2RST;
RCC->APB1RSTR &= ~RCC_APB1RSTR_USART2RST;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN;
RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
GPIO_Set(GPIOA,PIN2|PIN3,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_50M,GPIO_PUPD_PU);
GPIO_AF_Set(GPIOA,2,7);
GPIO_AF_Set(GPIOA,3,7);
GPIO_Set(GPIOA,PIN4,GPIO_MODE_OUT,GPIO_OTYPE_PP,GPIO_SPEED_50M,GPIO_PUPD_NONE);
USART2->BRR = mantissa;
USART2->CR1 = 0;
USART2->CR1 |= (0<<15); //16倍过采样
if(parity == 2)
{
USART2->CR1 |= 2<<9; //使能奇偶校验,偶校验方式
USART2->CR1 |= (1<<12); //1个起始位,9个数据位
}
else if(parity == 1)
{
USART2->CR1 |= 3<<9; //使能奇偶校验,奇校验方式
USART2->CR1 |= (1<<12); //1个起始位,9个数据位
}
else
{
USART2->CR1 &= ~(1<<10);
USART2->CR1 |= (0<<12); //1个起始位,8个数据位
}
if(stopbits == 0)
USART2->CR2 |= (0 << 12); //停止位设置
else if(stopbits == 1)
USART2->CR2 |= (2 << 12); //停止位设置
else
USART2->CR2 |= (0 << 12); //停止位设置
USART2->CR1 |= (1<<2)|(1<<3); //串口收发使能
USART2->SR &= ~(1<<6); //清串口发送完成中断标志位
MY_NVIC_Init(7,0,USART2_IRQn,4);
USART2->CR3 &= ~( (1<<6) | (1<<7) ); //关闭串口DMA收发
USART2->CR1 |= (1<<13); //使能串口
return 0;
}
__task void hmiusart_task(void)
{
initUsart2(42,19200,0,0);
HMI485RCV();
while(1)
{
usRcvLength = USART2_DMAR(ucHmiRxBuf,MBBUFSIZE,100);
if(usRcvLength > 0)
{
//代表接收到数据,进行数据解包处理
HMI485SEND();
USART2_DMAT(ucHmiTxBuf,usHmiTxDATALen);
}
}
}
|
|