初级会员

- 积分
- 134
- 金钱
- 134
- 注册时间
- 2012-6-3
- 在线时间
- 21 小时
|
1金钱
使用stm32F407的USART1 做DMA发送,发现发送的长度和设置的长度会出现差异,比如我设置发送40个字节,总会出现少于40个字节的现象,并且发现一般在第四个字节之后数据就不对了,找了好几天找不到问题,希望大侠帮忙看看,使用USCOSIII和不使用操作系统都试过了,都不行
/*********************************************************************
* 初始化串口
**********************************************************************/
void Init_USART1(u32 BaudRate)
{
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitTypeDef NVIC_JnitStructure_DMA;
DMA_InitTypeDef DMA_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1时钟
//串口1对应引脚复用映射
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIOA9复用为USART1
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10复用为USART1
//USART1端口配置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9与GPIOA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9,PA10
//USART1 初始化设置
USART_InitStructure.USART_BaudRate = BaudRate;//波特率设置
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_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; //收发模式
USART_Init(USART1, &USART_InitStructure); //初始化串口1
USART_Cmd(USART1, ENABLE); //使能串口1
//USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启相关中断
//Usart1 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口1中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器、
//串口发DMA配置
//启动DMA时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
//DMA发送中断设置
NVIC_JnitStructure_DMA.NVIC_IRQChannel = DMA2_Stream7_IRQn;
NVIC_JnitStructure_DMA.NVIC_IRQChannelPreemptionPriority = 3;
NVIC_JnitStructure_DMA.NVIC_IRQChannelSubPriority = 0;
NVIC_JnitStructure_DMA.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_JnitStructure_DMA);
//DMA通道配置
DMA_DeInit(DMA2_Stream7);
while (DMA_GetCmdStatus(DMA2_Stream7) != DISABLE){}//等待DMA可配置
DMA_InitStructure.DMA_Channel = DMA_Channel_4;
//外设地址
DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_ADDRESS;//(uint32_t)(&USART1->DR);
//内存地址
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)tx;
//dma传输方向
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
//设置DMA在传输时缓冲区的长度
DMA_InitStructure.DMA_BufferSize = 8;
//设置DMA的外设递增模式,一个外设
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
//设置DMA的内存递增模式
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
//外设数据字长
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
//内存数据字长
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
//设置DMA的传输模式
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
//设置DMA的优先级别
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
//指定如果FIFO模式或直接模式将用于指定的流 : 不使能FIFO模式
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
//指定了FIFO阈值水平
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
//指定的Burst转移配置内存传输
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
//指定的Burst转移配置外围转移 */
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
//配置DMA2的通道
DMA_Init(DMA2_Stream7, &DMA_InitStructure);
//使能中断
DMA_ITConfig(DMA2_Stream7,DMA_IT_TC,ENABLE);
DMA_Cmd(DMA2_Stream7,DISABLE);
//串口收DMA配置
//启动DMA时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
//DMA通道配置
DMA_DeInit(DMA2_Stream2);
while (DMA_GetCmdStatus(DMA2_Stream2) != DISABLE){}//等待DMA可配置
DMA_InitStructure.DMA_Channel = DMA_Channel_4;
//外设地址
DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_ADDRESS;//(uint32_t)(&USART1->DR);
//内存地址
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)tx;
//dma传输方向
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
//设置DMA在传输时缓冲区的长度
DMA_InitStructure.DMA_BufferSize = 8;
//设置DMA的外设递增模式,一个外设
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
//设置DMA的内存递增模式
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
//外设数据字长
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
//内存数据字长
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
//设置DMA的传输模式
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
//设置DMA的优先级别
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
//指定如果FIFO模式或直接模式将用于指定的流 : 不使能FIFO模式
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
//指定了FIFO阈值水平
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
//指定的Burst转移配置内存传输
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
//指定的Burst转移配置外围转移 */
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
//配置DMA1的通道
DMA_Init(DMA2_Stream2, &DMA_InitStructure);
//使能通道
DMA_Cmd(DMA2_Stream2,ENABLE);
//采用DMA方式发送
USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);
//采用DMA方式接收
USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);
//中断配置
USART_ITConfig(USART1,USART_IT_TC,DISABLE);
USART_ITConfig(USART1,USART_IT_RXNE,DISABLE);
USART_ITConfig(USART1,USART_IT_TXE,DISABLE);
USART_ITConfig(USART1,USART_IT_IDLE,ENABLE);
//启动串口
USART_Cmd(USART1, ENABLE);
}
/*********************************************************************
* 接口函数 MA发送中断处理函数
**********************************************************************/
void DMA2_Stream7_IRQHandler(void)
{
#if SYSTEM_SUPPORT_OS //使用UCOS操作系统
OSIntEnter();
#endif
if(DMA_GetITStatus(DMA2_Stream7,DMA_IT_TCIF7) != RESET)
{
//清除标志位
DMA_ClearFlag(DMA2_Stream7,DMA_FLAG_TCIF7);
//关闭DMA
DMA_Cmd(DMA2_Stream7,DISABLE);
//打开发送完成中断,发送最后两个字节
// USART_ITConfig(USART1,USART_IT_TC,ENABLE);
}
#if SYSTEM_SUPPORT_OS
OSIntExit(); //退出中断
#endif
//
}
/*********************************************************************
*参数:data:发送数据存放地址
* size:发送数据字节数
**********************************************************************/
void USART1_TX(u16 size)
{
//等待空闲
// while (Flag_Tx_Gsm_Busy);
// Flag_Tx_Gsm_Busy = 1;
// //复制数据
DMA_Cmd(DMA2_Stream7,DISABLE);
//memcpy(USART1_TX_Buffer,data,size);
while (DMA_GetCmdStatus(DMA2_Stream7) != DISABLE){}//等待DMA可配置
//设置传输数据长度
DMA_SetCurrDataCounter(DMA2_Stream7,size);
//打开DMA,开始发送
DMA_Cmd(DMA2_Stream7,ENABLE);
}
/*********************************************************************
* 处理发送完成中断
*返回:0:未产生,1:已经产生
**********************************************************************/
uint8_t USART1_TXend(void)
{
if(USART_GetITStatus(USART1, USART_IT_TC) != RESET)
{
//关闭发送完成中断
USART_ITConfig(USART2,USART_IT_TC,DISABLE);
//发送完成
USART1_Tx_STA = 0;
return 1;
}
return 0;
}
/*********************************************************************
* 处理接收完成中断
*参数:buf:接收的数据
* len:接收的数据长度
*返回:0:未产生,其他:已经产生,此值为接收的数据长度
**********************************************************************/
u8 USART1_DMA_Rx(u8 *buf)
{
uint16_t len = 0;
//接收完成中断
if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)
{
USART1->SR;
USART1->DR; //清USART_IT_IDLE标志
//关闭DMA
DMA_Cmd(DMA2_Stream2,DISABLE);
//清除标志位
DMA_ClearFlag(DMA2_Stream2,DMA_FLAG_TCIF2);
//获得接收帧帧长
len = USART1_Rx_Len - DMA_GetCurrDataCounter(DMA2_Stream2);
// memcpy(buf,USART_RX_BUF,len);
//设置传输数据长度
DMA_SetCurrDataCounter(DMA2_Stream2,USART1_Rx_Len);
//打开DMA
DMA_Cmd(DMA2_Stream2,ENABLE);
return len;
}
return 0;
}
void USART1_IRQHandler(void) //串口1中断服务程序
{
u8 Res;
#if SYSTEM_SUPPORT_OS //使用UCOS操作系统
OSIntEnter();
#endif
Res = USART1_DMA_Rx(USART_RX_BUF);
USART1_TXend();
// if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
// {
// Res =USART_ReceiveData(USART1);//(USART1->DR); //读取接收到的数据
// USART_RX_BUF[0]=Res;
// if((USART_RX_STA&0x8000)==0)//接收未完成
// {
// if(USART_RX_STA&0x4000)//接收到了0x0d
// {
// if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
// else USART_RX_STA|=0x8000; //接收完成了
// }
// else //还没收到0X0D
// {
// if(Res==0x0d)USART_RX_STA|=0x4000;
// else
// {
// USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
// USART_RX_STA++;
// if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收
// }
// }
// }
// }
//读SR后读DR清除Idle
USART2->SR;
USART2->DR;
USART_ClearITPendingBit(USART1, USART_IT_TC);
// USART_ClearITPendingBit(USART1, USART_IT_IDLE);
#if SYSTEM_SUPPORT_OS
OSIntExit(); //退出中断
#endif
}
#endif
u8 tx[254];
int main(void)
{
int i;
delay_init(168); //延时初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断分组配置
Init_USART1(115200);
USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE); //使能串口1的DMA发送
LED_Init(); //LED初始化
for(i=0;i<254;i++)
tx=i;
while(1)
{
USART1_TX(40);
// for(i=0;i<40;i++)
// {USART_SendData(USART1,tx);
// delay_us(100);
// }
delay_ms(1000);
LED0= !LED0;
}
}

缓冲区的数据也都没问题啊

收到长度对,数据也不对,中间数据也不一样,但是数组是我写死的

|
|