OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 9966|回复: 0

STM32 的Usart1数据发送 DMA方式的疑问:

[复制链接]

21

主题

123

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
355
金钱
355
注册时间
2012-3-11
在线时间
49 小时
发表于 2012-7-11 14:36:05 | 显示全部楼层 |阅读模式
DMA发送经过测试是好的,但是DMA接收有问题,一个字节是对的,2个以上字节就第一个是对的,其他错,请高手帮忙看一下程序:
注:
//#define BUF_SIZE 500 
//
中断优先级初始化如下:
void InterruptInit(void)
{
NVIC_InitTypeDef   NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}

串口初始化程序如下:
void UART_Init(void)
{
GPIO_InitTypeDef   GPIO_InitStructure;
USART_InitTypeDef  USART_InitStructure;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//USART1 引脚初始化
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure);

USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_9b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_Even;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1,ENABLE);
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);
USART1_RX;
}
//DMA发送
void USART1_SendData(uint8_t *data,uint16_t length)
{
DMA_InitTypeDef    DMA_InitStructure;
USART1_TX;
DMA_DeInit(DMA1_Channel4);
DMA_InitStructure.DMA_PeripheralBaseAddr =(uint32_t)(&USART1->DR); //设置外设地址
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)data;    //设置存储器地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;    //外设作为数据传输目的地
DMA_InitStructure.DMA_BufferSize = length;    //设置DMA通道缓存大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  //外设地址寄存器地址不变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;   //内存地址寄存器地址递增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;     //工作在正常缓存模式
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //非内存到内存传输
DMA_Init(DMA1_Channel4, &DMA_InitStructure);
DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE);
USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);
DMA_Cmd(DMA1_Channel4,ENABLE);
}

//串口DMA发送中断函数:
void DMA1_Channel4_IRQHandler(void)
{
if(DMA_GetITStatus(DMA1_IT_TC4)==SET)
{
DMA_ClearITPendingBit(DMA1_IT_TC4);
USART_ClearITPendingBit(USART1,USART_IT_TC);//波特率较低时需要这一句
USART_ITConfig(USART1,USART_IT_TC,ENABLE);
}
}
//串口1中断处理函数

void USART1_IRQHandler(void)
{
DMA_InitTypeDef    DMA_InitStructure;
uint32_t tmp=0;//无意义,仅用于清除IDLE标志位,由软件序列清除该位(先读USART_SR,然后读USART_DR)
if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET) //收到第一个字节后开DMA,关接收中断,开空闲中断
{
USART_ClearITPendingBit(USART1,USART_IT_RXNE);
USART_ITConfig(USART1,USART_IT_RXNE,DISABLE);
USART_ITConfig(USART1,USART_IT_IDLE,ENABLE);
DMA_DeInit(DMA1_Channel5);
DMA_InitStructure.DMA_PeripheralBaseAddr =(uint32_t)(&USART1->DR);
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ModBusData.RxBuf[0];
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize =BUF_SIZE-1;//
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode =DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel5, &DMA_InitStructure);
DMA_Cmd(DMA1_Channel5,ENABLE);
}
else if(USART_GetITStatus(USART1,USART_IT_IDLE)==SET) //收到最后一个字节后清除空闲标志,取数据,关DMA,开接收中断,关空闲中断
{
tmp|=USART1->SR;//先读USART_SR
tmp|=USART1->DR;//然后读USART_DR
{
ModBusData.PackLen=BUF_SIZE-1-DMA_GetCurrDataCounter(DMA1_Channel5);//ModBusData.PackLen   
DMA_Cmd(DMA1_Channel5,DISABLE);
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
USART_ITConfig(USART1,USART_IT_IDLE,DISABLE);
if(ModBusData.PackLen>3)      //串口发送大于3,就置位接收结束标志,把ModBusData.PackLen>3改成ModBusData.PackLen>0,只能接收一个是对的,大于一个就不对了
get_a_pack=0x01;
}
}
else if(USART_GetITStatus(USART1,USART_IT_TC)==SET)//最后一个数据发送完以后,置成接收状态
{
USART_ClearITPendingBit(USART1,USART_IT_TC);
USART_ITConfig(USART1,USART_IT_TC,DISABLE);
USART1_RX;
}
}
主程序:
int main(void)
{
init_stm32();
TaskInit();
while (1)
{
    if(get_a_pack == 1)
    {
       USART1_SendData (&ModBusData.RxBuf[0],ModBusData.PackLen);//将接收到的数据再发出去,送到上位机
      get_a_pack=0;//接收接收标志清零
    }

}
这辈子只会两件事:这也不会,那也不会!
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-26 17:45

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表