系统供电3.3V,USART3串口3中断接收初始化(PD8,PD9)与DMA空闲中断接收,115200波特率,采用中断接收或者DMA中断接收(通过宏定义切换是普通中断接收还是DMA中断接收:#define USART3_DMA 1),主动发送,接收处理函数为log串口测试指令,不用在意,移植时候可以根据项目需求,替换成自己的应用代码即可。同样,前面是头文件代码,后面是应用代码,仅做记录,方便以后移植应用,代码已实测。
#ifndef __USART3_H__
#define __USART3_H__
#include "usart.h"
#define USART3_RX_LEN 512 //接受数据缓存区长度
#define USART3_TX_LEN 512 //接受数据缓存区长度
#define Zero 0
#define One 1
#define Two 2
#define Three 3
#define Four 4
#define Five 5
#define Six 6
#define Seven 7
#define Eight 8
#define Nine 9
#define Ten 10
struct __USART3_ //usart3 structure
{
u8 rxBuf[USART3_RX_LEN]; //接收缓存区
u8 txBuf[USART3_TX_LEN]; //发送缓存区
u16 rxLen; //串口1接收到的数据长度
u16 txLen; //串口1接收到的数据长度
u8 rxOk; //RX 数据接收完成标志
u8 txOk; // tx数据发送ready flag
u32 rxTimeOut;
u8 debug;
};
extern struct __USART3_ Usart3 ; //usart3 structure
void usart3Init(u32 baudRate ); //usart initial
void usart3Deal(void); //usart data deal
#endif
#include "usart3.h"
#define USART3_DMA 1
struct __USART3_ Usart3 ; //usart3 structure
void usart3IntInit(u32 baudRate) //usart initial,interupt rx mode
{
GPIO_InitType GPIO_InitStructure;
USART_InitType USART_InitStructure;
NVIC_InitType NVIC_InitStructure;
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO | RCC_APB2_PERIPH_GPIOD, ENABLE); //enable port clk
// GPIO_ConfigPinRemap(GPIO_RMP_SW_JTAG_SW_ENABLE, ENABLE); //只需要SWD功能
RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_USART3, ENABLE); //enable usart clk
GPIO_InitStructure.Pin = GPIO_PIN_8; //TX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitPeripheral(GPIOD, &GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIO_PIN_9; //RX
//GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //GPIO_Mode_IPU
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //edit by kevin
GPIO_InitPeripheral(GPIOD, &GPIO_InitStructure);
GPIO_ConfigPinRemap(GPIO_ALL_RMP_USART3,ENABLE); //GPIO remap
USART_InitStructure.BaudRate = baudRate; // Baud rate
USART_InitStructure.WordLength = USART_WL_8B; // 8N1
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(USART3, &USART_InitStructure);// init uart
USART_Enable(USART3, ENABLE);// enable uart
USART_ClrFlag(USART3, USART_FLAG_TXC); //清除标志位
USART_ConfigInt(USART3, USART_INT_RXDNE, ENABLE); //rx interupt enable。
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void usart3DmaInit(u32 baudRate ) //usart initial,DMA 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_AFIO | RCC_APB2_PERIPH_GPIOD, ENABLE); //enable port clk
// GPIO_ConfigPinRemap(GPIO_RMP_SW_JTAG_SW_ENABLE, ENABLE);//只需要SWD功能
RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_USART3, ENABLE); //enable usart clk
GPIO_InitStructure.Pin = GPIO_PIN_8; //TX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitPeripheral(GPIOD, &GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIO_PIN_9; //RX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //GPIO_Mode_IPU
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //edit by kevin
GPIO_InitPeripheral(GPIOD, &GPIO_InitStructure);
GPIO_ConfigPinRemap(GPIO_ALL_RMP_USART3,ENABLE); //GPIO remap
USART_InitStructure.BaudRate = baudRate; // Baud rate
USART_InitStructure.WordLength = USART_WL_8B; // 8N1
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(USART3, &USART_InitStructure);// init uart
// USART_Enable(USART3, ENABLE);// enable uart
// USART_ClrFlag(USART3, USART_FLAG_TXC); //清除标志位
// USART_ConfigInt(USART3, USART_INT_RXDNE, ENABLE); //rx interupt enable。
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
DMA_DeInit(DMA1_CH3);
DMA_InitStructure.PeriphAddr = (USART3_BASE + 0x04); //外设地址
DMA_InitStructure.MemAddr = (uint32_t)Usart3.rxBuf; //缓冲区地址
DMA_InitStructure.BufSize = USART3_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_CH3, &DMA_InitStructure);
USART_EnableDMA(USART3, USART_DMAREQ_RX, ENABLE); //使能接收DMA
USART_ConfigInt(USART3, USART_INT_IDLEF, ENABLE); //使能空闲中断
DMA_EnableChannel(DMA1_CH3, ENABLE);//使能DMA
USART_Enable(USART3, ENABLE);
}
void usart3Init(u32 baudRate )
{
// USART_EnableDMA(USART3, USART_DMAREQ_RX, DISABLE); //使能接收DMA
#ifdef USART3_DMA
usart3DmaInit(baudRate); //usart initial,DMA rx mode
#else
usart3IntInit(baudRate); //usart initial,interupt rx mode
#endif
}
void usart3RxBuf(u8 rxData) //usart data receiving,
{
static u16 len = 0; //rx length
//static u8 crcSum = 0; //crc check sum
static u8 step = 0; //rx step
Usart3.rxBuf[len] = rxData; //把接收到的通信数据赋值给数组
switch (step)
{
case Zero:
if (Usart3.rxBuf[len] == 'A') //
{
//crcSum = 0;
len = One; //采用复赋值语句,加法语句运行时间较长,需要几百个时钟周期,赋值只需要一个时钟周期
step = One; //修改接收步骤
}
break;
case One:
if (Usart3.rxBuf[len] == 'T')
{
len = Two;
step = Two; //修改接收步骤
}
else
{
len = Zero; //数据不对重新接收
step = Zero; //修改接收步骤
}
break;
case Two: //接收数据包有效长度
//crcSum = 0;
//crcSum ^= Usart3.rxBuf[len] ;
len = Three;
step = Three; //修改接收步骤
break;
case Three: //接收有效数据
//crcSum ^= Usart3.rxBuf[len++];
if (len<USART3_RX_LEN) //Maximum rx length limit
{
if(Usart3.rxBuf[len] == '#') //received the complete AT command package.
{
// Usart3.rxLen = len+1;
// Usart3.rxReadyFlag = OK;
ZrdCommand.rxLen = len+1;
ZrdCommand.rxOkFlag = OK;
memcpy(ZrdCommand.rxBuf,Usart3.rxBuf,ZrdCommand.rxLen); //copy the complete AT command package to ZrdCommand.rxBuf
len =0; //clear the rx length
step = Zero; //clear the rx step
}
else
{
len++; //rx len++ ,ready to receive the next data
}
}
else
{
len = 0;
step = Zero; //
}
break;
case Four: //
break;
default:
len = 0;
step = Zero; //
break;
}
}
#ifdef USART3_DMA //usart initial,DMA rx mode
void USART3_IRQHandler(void)
{
uint32_t temp;
if ( (USART_GetIntStatus(USART3, USART_INT_OREF) != RESET) //Overrun error
|| (USART_GetIntStatus(USART3, USART_INT_NEF) != RESET) //Noise error flag
|| (USART_GetIntStatus(USART3, USART_INT_FEF) != RESET) //Framing error
)
{
temp = USART3->STS;
temp = USART3->DAT;
}
if((USART_GetIntStatus(USART3,USART_INT_IDLEF) != RESET))//IDLE line detected
{
temp = USART3->STS;//清IDLE标志
temp = USART3->DAT;
DMA_EnableChannel(DMA1_CH3,DISABLE);
temp = DMA_GetCurrDataCounter(DMA1_CH3); //应该是当前接收数据缓存器剩余空间长度
Usart3.rxLen = USART3_RX_LEN - temp; //计算出当前接收数据长度
DMA1_CH3->TXNUM=USART3_RX_LEN;
DMA_EnableChannel(DMA1_CH3,ENABLE);
if(Usart3.rxLen<=USART3_RX_LEN)
Usart3.rxOk =1; //数据包接收完成标志
}
}
#else //usart initial,interupt rx mode
void USART3_IRQHandler(void)
{
u8 rec;
if(USART_GetIntStatus(USART3,USART_INT_RXDNE)==SET)
{
USART_ClrIntPendingBit(USART3,USART_INT_RXDNE);
rec=USART_ReceiveData(USART3); //read usart data:1byte
usart3RxBuf(rec); //rx data put into Usart3.rxBuf[len],and judge receiving complete.
}
//溢出-如果发生溢出需要先读SR,再读DR寄存器 则可清除不断入中断的问题
if(USART_GetFlagStatus(USART3,USART_FLAG_OREF)==SET)
{
USART_ClrFlag(USART3,USART_FLAG_OREF); //读SR
USART_ReceiveData(USART3); //读DR
}
}
#endif
void usart3Deal(void) //This code just for testing.
{
if(Usart3.rxTimeOut>USART_TIME_OUT) //Receive timeout processing
{
}
if(Usart3.rxOk == OK) //This code just for test.
{
Usart3.rxOk = NOT_OK;
// ZrdCommand.rxOkFlag = OK;
ZrdCommand.rxLen = Usart3.rxLen;
memcpy(ZrdCommand.rxBuf,Usart3.rxBuf,ZrdCommand.rxLen); //
zrdAtCmdParser(ZrdCommand.rxBuf,ZrdCommand.rxLen);
memset(Usart3.rxBuf,0,Usart3.rxLen); //清零串口数据缓存
}
}