系统供电3.3V,USART1串口1中断接收初始化(PB6,PB7)与DMA空闲中断接收,115200波特率,采用中断接收或者DMA中断接收(通过宏定义切换是普通中断接收还是DMA中断接收:#define USART1_DMA 1),主动发送,接收处理函数为EC800串口指令,不用在意,移植时候可以根据项目需求,替换成自己的应用代码即可。同样,前面是头文件代码,后面是应用代码,仅做记录,方便以后移植应用,代码已实测。
问题记录:DMA模式接收EC800数据,空闲间隔无法调整,数据包的完整性无法保证,容易出现解析错误。所以采用中断模式,通过调整空闲时间,以使数据接收时序符合外接模组要求,保证数据完整性,解析正确。
#ifndef __USART1_H__
#define __USART1_H__
#include "main.h" //
#define USART1_RX_LEN 4096*2 //接受数据缓存区长度
#define USART1_TX_LEN 4096 //接受数据缓存区长度
#define USART1_RX_TIMEOUT 10 //接受数据缓存区长度
struct __USART1_ //串口数据结构体
{
char rxBuf[USART1_RX_LEN]; //接收缓存区
char txBuf[USART1_TX_LEN]; //发送缓存区
u16 rxLen; //串口1接收到的数据长度
u16 txLen; //串口1接收到的数据长度
u8 rxOk; //RX 数据接收完成标志
u8 txOk; //tx数据发送ready flag
u32 rxTimeOut;
};
extern struct __USART1_ Usart1; //串口数据结构体
void usart1Init(u32 baudRate ); //usart1 initial
void usart1Deal(void); //usart data deal,figure out whether it's data EC800 or data JT808.
#endif
#include "usart1.h"
struct __USART1_ Usart1; //串口数据结构体
// #define USART1_DMA 1
void usart1DmaInit(u32 baudRate ) //usart1 initial
{
GPIO_InitType GPIO_InitStructure;
USART_InitType USART_InitStructure;
NVIC_InitType NVIC_InitStructure;
DMA_InitType DMA_InitStructure;
RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_DMA1, ENABLE);
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB|RCC_APB2_PERIPH_AFIO,ENABLE);
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_USART1,ENABLE); //串口1时钟
GPIO_ConfigPinRemap(GPIO_RMP_USART1,ENABLE); //IO 复用
GPIO_InitStructure.Pin = GPIO_PIN_6; //TX
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIO_PIN_7;//PB7 RX
//GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //edit by kevin
GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
USART_InitStructure.BaudRate = baudRate; //波特率设置
USART_InitStructure.WordLength = USART_WL_8B;
USART_InitStructure.StopBits = USART_STPB_1;
USART_InitStructure.Parity = USART_PE_NO;
USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
USART_InitStructure.Mode = USART_MODE_RX | USART_MODE_TX;
USART_Init(USART1, &USART_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //串口1中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0; //抢占优先级1
NVIC_InitStructure.NVIC_IRQChannelSubPriority =0; //子优先级1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //中断通道使能
NVIC_Init(&NVIC_InitStructure); //根据配置设置
DMA_DeInit(DMA1_CH5);
DMA_InitStructure.PeriphAddr = (USART1_BASE + 0x04); //外设地址
DMA_InitStructure.MemAddr = (uint32_t)Usart1.rxBuf; //缓冲区地址
DMA_InitStructure.BufSize = USART1_RX_LEN; //传输大小(长度)
DMA_InitStructure.Direction = DMA_DIR_PERIPH_SRC; //方向:外设到内存
DMA_InitStructure.PeriphInc = DMA_PERIPH_INC_DISABLE; //外设地址不增
DMA_InitStructure.DMA_MemoryInc = DMA_MEM_INC_ENABLE; //内存地址自增
DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_SIZE_BYTE; //外设传输数据宽度
DMA_InitStructure.MemDataSize = DMA_MemoryDataSize_Byte; //内存传输数据宽度
DMA_InitStructure.CircularMode = DMA_MODE_CIRCULAR ; //DMA_MODE_NORMAL DMA模式
DMA_InitStructure.Priority = DMA_PRIORITY_VERY_HIGH; //通道优先级
DMA_InitStructure.Mem2Mem = DMA_M2M_DISABLE; //存储器到存储器模式不是能
DMA_Init(DMA1_CH5, &DMA_InitStructure);
USART_EnableDMA(USART1, USART_DMAREQ_RX, ENABLE); //使能接收DMA
USART_ConfigInt(USART1, USART_INT_IDLEF, ENABLE); //使能空闲中断
DMA_EnableChannel(DMA1_CH5, ENABLE);//使能DMA
USART_Enable(USART1, ENABLE);
}
void usart1IntInit(u32 baudRate) //usart initial,interupt rx mode
{
GPIO_InitType GPIO_InitStructure;
USART_InitType USART_InitStructure;
NVIC_InitType NVIC_InitStructure;
// DMA_InitType DMA_InitStructure;
// RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_DMA1, ENABLE);
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB|RCC_APB2_PERIPH_AFIO,ENABLE);
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_USART1,ENABLE); //串口1时钟
GPIO_ConfigPinRemap(GPIO_RMP_SW_JTAG_SW_ENABLE, ENABLE);//
GPIO_InitStructure.Pin = GPIO_PIN_6; //TX
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIO_PIN_7;//PB7 RX
//GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //edit by kevin
GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
USART_InitStructure.BaudRate = baudRate; //波特率设置
USART_InitStructure.WordLength = USART_WL_8B;
USART_InitStructure.StopBits = USART_STPB_1;
USART_InitStructure.Parity = USART_PE_NO;
USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
USART_InitStructure.Mode = USART_MODE_RX | USART_MODE_TX;
USART_Init(USART1, &USART_InitStructure);
USART_Enable(USART1, ENABLE);// enable uart
USART_ClrFlag(USART1, USART_FLAG_TXC); //清除标志位
USART_ConfigInt(USART1, USART_INT_RXDNE, ENABLE); //rx interupt enabl
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //串口1中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0; //抢占优先级1
NVIC_InitStructure.NVIC_IRQChannelSubPriority =0; //子优先级1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //中断通道使能
NVIC_Init(&NVIC_InitStructure); //根据配置设置
// DMA_DeInit(DMA1_CH5);
// DMA_InitStructure.PeriphAddr = (USART1_BASE + 0x04); //外设地址
// DMA_InitStructure.MemAddr = (uint32_t)Usart1.rxBuf; //缓冲区地址
// DMA_InitStructure.BufSize = USART1_RX_LEN; //传输大小(长度)
// DMA_InitStructure.Direction = DMA_DIR_PERIPH_SRC; //方向:外设到内存
// DMA_InitStructure.PeriphInc = DMA_PERIPH_INC_DISABLE; //外设地址不增
// DMA_InitStructure.DMA_MemoryInc = DMA_MEM_INC_ENABLE; //内存地址自增
// DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_SIZE_BYTE; //外设传输数据宽度
// DMA_InitStructure.MemDataSize = DMA_MemoryDataSize_Byte; //内存传输数据宽度
// DMA_InitStructure.CircularMode = DMA_MODE_CIRCULAR ; //DMA_MODE_NORMAL DMA模式
// DMA_InitStructure.Priority = DMA_PRIORITY_VERY_HIGH; //通道优先级
// DMA_InitStructure.Mem2Mem = DMA_M2M_DISABLE; //存储器到存储器模式不是能
// DMA_Init(DMA1_CH5, &DMA_InitStructure);
// USART_EnableDMA(USART1, USART_DMAREQ_RX, ENABLE); //使能接收DMA
// USART_ConfigInt(USART1, USART_INT_IDLEF, ENABLE); //使能空闲中断
// DMA_EnableChannel(DMA1_CH5, ENABLE);//使能DMA
// USART_Enable(USART1, ENABLE);
}
void usart1Init(u32 baudRate )
{
#ifdef USART1_DMA
usart1DmaInit(baudRate); //usart initial,DMA rx mode
#else
usart1IntInit(baudRate); //usart initial,interupt rx mode
#endif
}
void usart1RxBuf(u8 rxData)
{
if(Usart1.rxLen<USART1_RX_LEN)
{
Usart1.rxBuf[Usart1.rxLen++] = rxData;
Usart1.rxTimeOut = 0;
}
}
#ifdef USART1_DMA
void USART1_IRQHandler(void) //重写串口中断处理函数
{
uint32_t temp;
if ( (USART_GetIntStatus(USART1, USART_INT_OREF) != RESET) //Overrun error
|| (USART_GetIntStatus(USART1, USART_INT_NEF) != RESET) //Noise error flag
|| (USART_GetIntStatus(USART1, USART_INT_FEF) != RESET) //Framing error
)
{
temp = USART1->STS;
temp = USART1->DAT;
}
if((USART_GetIntStatus(USART1,USART_INT_IDLEF) != RESET))//IDLE line detected
{
temp = USART1->STS;//清IDLE标志
temp = USART1->DAT;
DMA_EnableChannel(DMA1_CH5,DISABLE);
temp = DMA_GetCurrDataCounter(DMA1_CH5); //应该是当前接收数据缓存器剩余空间长度
Usart1.rxLen = USART1_RX_LEN - temp; //计算出当前接收数据长度
DMA1_CH5->TXNUM=USART1_RX_LEN;
DMA_EnableChannel(DMA1_CH5,ENABLE);
if(Usart1.rxLen<=USART1_RX_LEN) Usart1.rxOkFlag =1; //数据包接收完成标志
}
}
#else
void USART1_IRQHandler(void)
{
u8 rec;
if(USART_GetIntStatus(USART1,USART_INT_RXDNE)==SET)
{
USART_ClrIntPendingBit(USART1,USART_INT_RXDNE);
rec=USART_ReceiveData(USART1); //read usart data:1byte
usart1RxBuf(rec); //rx data put into usart.rxBuf[len],and judge receiving complete.
}
//溢出-如果发生溢出需要先读SR,再读DR寄存器 则可清除不断入中断的问题
if(USART_GetFlagStatus(USART1,USART_FLAG_OREF)==SET)
{
USART_ClrFlag(USART1,USART_FLAG_OREF); //读SR
USART_ReceiveData(USART1); //读DR
}
}
#endif
#ifdef USART1_DMA
void usart1Deal(void) //usart data deal,figure out whether it's data EC800 or data JT808.
{
if(Usart1.rxOkFlag == 1) //数据包接收完成标志
// if((Usart1.rxLen>1)&&(Usart1.rxTimeOut>100))
{
Usart1.rxOkFlag =0;
// if(Usart1.rxBuf[0]==0x7E && Usart1.rxBuf[Usart1.rxLen-1]==0x7E) //JT808数据包
// {
// memcpy(Jt808.rxBuf,Usart1.rxBuf,Usart1.rxLen); //copy the data to buf
// Jt808.rxLen = Usart1.rxLen; //
// Jt808.rxOk = OK; //jt808接收数据包完成标志置位
// }
// else //EC800 AT指令反馈或自动上传数据
{
memcpy(Ec800.rxBuf,Usart1.rxBuf,Usart1.rxLen); //copy the data to buf
Ec800.rxBufLen = Usart1.rxLen; //
Ec800.rxOkFlag = OK;
//log_debug("EC800 receive control CMD ********************************************************* \r\n"); //This code just for test.Edit by kevin.
}
// logSend(Usart1.rxBuf,Usart1.rxLen); //发送整包数据到log串口
memset(Usart1.rxBuf,0,Usart1.rxLen); //清零串口数据缓存
Usart1.rxTimeOut = 0;
Usart1.rxLen = 0;
}
}
#else
void usart1Deal(void) //usart data deal,figure out whether it's data EC800 or data JT808.
{
if((Usart1.rxLen>1)&&(Usart1.rxTimeOut>USART1_RX_TIMEOUT))
{
Usart1.rxTimeOut = 0;
memcpy(Ec800.rxBuf,Usart1.rxBuf,Usart1.rxLen); //copy the data to buf
Ec800.rxLen = Usart1.rxLen; //
memset(Usart1.rxBuf,0,Usart1.rxLen); //清零串口数据缓存
Usart1.rxLen = 0; //
ec800Parser(Ec800.rxBuf,Ec800.rxLen); //EC800数据解析。
}
}
#endif