stm32f103rc串口接收(485)使用DMA和IDLE的方式
·
可接收任意长度字节
贴代码
dma_idle.c
#include "stm32f10x.h" // Device header
#include "dma_idle.h" // Device header
uint32_t timeout1=0;
//关闭两秒485 熄屏
uint32_t two_second;
//收到一帧数据标志位
uint8_t receive_flag=0;
//收到字符
uint8_t DMA_Rece_Buf[120];
//长度
uint16_t DMA_Rec_Len=100;
//收到长度
uint16_t Usart1_Rec_Cnt;
//初始化IO 串口1
//bound:波特率
void uart_init(u32 bound)
{
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA,ENABLE); //使能 USART1,GPIOA时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能DMA传输
// RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);//使能USART2时钟
USART_DeInit(USART1); //复位串口1
//USART1_TX PA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA9
//USART1_RX PA.10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA10
//Usart1 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
//USART 初始化设置
USART_InitStructure.USART_BaudRate = bound;
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); //初始化串口
USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);//开启空闲中断
USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE); //使能串口1 DMA接收
USART_Cmd(USART1, ENABLE); //使能串口
//相应的DMA配置
DMA_DeInit(DMA1_Channel5); //将DMA的通道5寄存器重设为缺省值 串口1对应的是DMA通道5
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR; //DMA外设usart基地址
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)DMA_Rece_Buf; //DMA内存基地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //数据传输方向,从外设读取发送到内存
DMA_InitStructure.DMA_BufferSize = DMA_Rec_Len; //DMA通道的DMA缓存的大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器不变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器递增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //数据宽度为8位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //数据宽度为8位
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //工作在正常缓存模式
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //DMA通道 x拥有中优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x没有设置为内存到内存传输
DMA_Init(DMA1_Channel5, &DMA_InitStructure); //根据DMA_InitStruct中指定的参数初始化DMA的通道
DMA_Cmd(DMA1_Channel5, ENABLE); //正式驱动DMA传输
//DE置高 发数据前才置低 发完再置高
GPIO_SetBits(GPIOA,GPIO_Pin_11);
}
//重新恢复DMA指针
void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx)
{
DMA_Cmd(DMA_CHx, DISABLE ); //关闭USART1 TX DMA1所指示的通道
DMA_SetCurrDataCounter(DMA_CHx,DMA_Rec_Len);//DMA通道的DMA缓存的大小
DMA_Cmd(DMA_CHx, ENABLE); //打开USART1 TX DMA1所指示的通道
}
//发送len个字节
//buf:发送区首地址
//len:发送的字节数
void Usart1_Send(u8 *buf,u8 len)
{
u8 t;
for(t=0;t<len;t++) //循环发送数据
{
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
USART_SendData(USART1,buf[t]);
}
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
}
//串口中断函数
void USART1_IRQHandler(void) //串口1中断服务程序
{
two_second=0;
if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
USART_ReceiveData(USART1);//读取数据注意:这句必须要,否则不能够清除中断标志位。
Usart1_Rec_Cnt = DMA_Rec_Len-DMA_GetCurrDataCounter(DMA1_Channel5); //算出接本帧数据长度
receive_flag=1;
// Usart1_Send((uint16_t*)DMA_Rece_Buf,Usart1_Rec_Cnt);
USART_ClearITPendingBit(USART1,USART_IT_IDLE); //清除中断标志
MYDMA_Enable(DMA1_Channel5); //恢复DMA指针,等待下一次的接收
}
}
dma_idle.h
#ifndef __DMA_IDLE_H__
#define __DMA_IDLE_H__
#include "stm32f10x.h" // Device header
extern uint8_t receive_flag;
extern uint8_t DMA_Rece_Buf[120];
extern uint16_t Usart1_Rec_Cnt;
extern uint32_t timeout1;
extern uint32_t two_second;
void uart_init(u32 bound);
void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx);
#endif
main.c
int main(void)
{
uart_init(9600);
Timer_Init();
CountSensor_Init();
LED_Init();
Led_Board_Init();
while(1)
{
//收到一帧
if(receive_flag==1)
{
if((DMA_Rece_Buf[2]*2+4)==Usart1_Rec_Cnt)
{
if(Is_BCC_Good(DMA_Rece_Buf,Usart1_Rec_Cnt))
{
if(DMA_Rece_Buf[0]==0x55&&DMA_Rece_Buf[1]==0xAA)
{
u8 i=3;
while(i<Usart1_Rec_Cnt)
{
//ID为0
if((DMA_Rece_Buf[i]>>3)==0x00)
{
// if((DMA_Rece_Buf[i]>>2)==1)
// {
// ; //闪
// }
// else
// {
// ; //不闪
// }
if((DMA_Rece_Buf[i]&0x03)==0x00)
{
display_end(); //黑
}
else if((DMA_Rece_Buf[i]&0x03)==0x01)
{
display_end();
gre_displaying(DMA_Rece_Buf[i+1]); //绿
}
else if((DMA_Rece_Buf[i]&0x03)==0x02)
{
display_end();
yel_displaying(DMA_Rece_Buf[i+1]); //黄
}
else if((DMA_Rece_Buf[i]&0x03)==0x03)
{
display_end();
red_displaying(DMA_Rece_Buf[i+1]); //红
}
}
i=i+2;
}
}
memset(DMA_Rece_Buf,0x00,sizeof(DMA_Rece_Buf));
receive_flag=0;
}
}
//不停的加 串口中断里有清零
two_second++;
}}}
void TIM2_IRQHandler(void)
{
//检查中断标志位
if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)
{
// //闪烁
// if(receive_flag==0)
// {
// timeout1++;
// if(timeout1>=1)
// {
// display_end();
// timeout1=0;
// }
// }
//断开两秒黑屏
if(two_second>=0x00600000)
{
display_end();
two_second=0;
}
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
}
}
校验 从第三个字符到校验的前一个进行异或 最后一个为校验位
bool Is_BCC_Good(u8 *pData, u8 nLength)
{
unsigned char Fcs = 0;
unsigned char i = 0;
pData++;
pData++;
for(i=0;i<nLength-2;i++)
{
Fcs = Fcs^*pData;
pData++;
}
if (Fcs == pData[nLength])
return 1;
else
return 0;
}
更多推荐
所有评论(0)