}
//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;//接收接收标志清零
}
}