📄 com.c
字号:
#include "..\main\include.h"
//#include "include.h"
/**************************************************************************************
* 变量原型:
* 变量说明:
**************************************************************************************/
/**************************************************************************************
* 函数原型:
* 函数功能:
* 输入参数:
* 输出参数:
* 函数说明:
**************************************************************************************/
#define USART1_RXNEirqEnable() USART1->CR1 |= USART_FLAG_RXNE //打开串口1接收中断
#define USART1_RXNEirqUnable() USART1->CR1 &= ~USART_FLAG_RXNE //关闭串口1接收中断
#define USART1_TXEirqEnable() USART1->CR1 |= USART_FLAG_TXE //打开串口1发送中断
#define USART1_TXEirqUnable() USART1->CR1 &= ~USART_FLAG_TXE //关闭串口1发送中断
#define USART1_TCirqEnable() USART1->CR1 |= USART_FLAG_TC //打开串口1发送完毕中断
#define USART1_TCirqUnable() USART1->CR1 &= ~USART_FLAG_TC //关闭串口1发送完毕中断
struPROTOCOL_Receive Receive;
struPROTOCOL_Send Send;
uint8* pRev;
uint8* pSend;
uint16 LocalAddr; //本机地址
void SetLocalAddr(uint16 temp)//本机地址
{
LocalAddr = temp;
}
//struPROTOCOL_Receive *getReceive(void)
//{
// return(&Receive);
//}
/*
功能:返回发送数据启始地址
注意:不含数据包的帧头信息
*/
uint8* getSendBuf(void)
{
while (Send.start != NO_SEND); //如果上一包数据没发送完将等待....
return(Send.buf);
}
/*
功能:返回接收数据启始地址
注意:
1、应该先判断接收到的数据包是请求还是应答
2、不含数据包的帧头信息
3、如果是应答不含状态信息
*/
uint8* getReceiveBuf(void)
{
return(Receive.buf);
}
//返回功能号
uint16 getCmd(void)
{
return(Receive.header.cmd);
}
/*
功能:检查接收数据包有没完成
返回值:
0=收到数据并且校验成功
1=收到数据并且校验失败
255=没收到数据
*/
uint8 testReceiveOver(void)
{
uint16 chk;
if (Receive.start == RECEIVE_OVER)//整个协议包接收完毕
{
PC_RS485Send_Enable(); //切换RS485到发送状态
//swp16HL(&Receive.header.chk);//协议包校验
chk = Check_Sum(Receive.buf - FRAME_HEADER_LEN, Receive.rrLen);
if (chk != 0)//校验错误
{
init_Receive();
return(1);
}
else//校验正确
{
swp16HL(&Receive.header.chk);//协议包校验.实际已经无用
swp16HL(&Receive.header.tLen);//协议包总长度
swp16HL(&Receive.header.object_addr);//目的地址
swp16HL(&Receive.header.cmd);//命令
if(Receive.header.object_addr == LocalAddr ||
Receive.header.object_addr == 0xffff)//地址相同||广播地
{
return(0);
}
else
{
init_Receive();
return(1);
}
}
}
else
{
return(255);
}
}
//初始化接收
void init_Receive(void)
{
Receive.start = NO_HEADER; //接收到头标志.还没收到头
Receive.rLen = 0; //接收数据量
Receive.header.chk = 0; //协议包校验
Receive.header.tLen = 0; //协议包总长度
Receive.header.object_addr = LocalAddr; //目的地址
Receive.header.cmd = 0; //命令
pRev = Receive.buf-FRAME_HEADER_LEN;//header;//接收数据指针
}
//初始化发送
void init_Send(void)
{
Send.sLen = 0;
Send.start = NO_SEND; //还没开始发送数据
Send.header.object_addr = LocalAddr; //目的地址
pSend = Send.buf - FRAME_HEADER_LEN; //发送数据指针
}
/**************************************************************************************
* 函数原型:void InitCom(void)
* 函数功能:清空接收和发送缓冲区,初始化串口,设置波特率
* 输入参数:
* 输出参数:
* 函数说明:
**************************************************************************************/
void InitCom(void)
{
init_Receive();
init_Send();
}
/*
在调用SendFun(),将判断前一次的数据包有没发送完毕
*/
void SendFun(void)
{
//while(send.start==START_SEND); //如果上一包数据没发送完将等待....
#ifdef PC_RS485//只有485芯片才延时,使用CAN芯片不延时
//Delayus(500);
Wait_ms(1);
#endif
Send.header.tLen += FRAME_HEADER_LEN; //数据包长度=数据长度+帧头长度
Send.sLen = Send.header.tLen; //发送数据长度
swp16HL(&Send.header.tLen);//协议包总长度
swp16HL(&Send.header.object_addr);//目的地址
swp16HL(&Send.header.cmd);//命令
pSend=Send.buf-FRAME_HEADER_LEN; //复位发送数据指针。注意:前2byte是校验
Send.header.chk=Check_Sum( pSend+2, Send.sLen-2 ); //计算校验和。注意:不能计算校验位
swp16HL(&Send.header.chk);//协议包校验
Send.start = START_SEND;//开始发送
USART1_TXEirqEnable(); //TI = 1;
}
//等待前一包数据发送完成
void WaitSendOver(void)
{
while (Send.start != NO_SEND); //如果上一包数据没发送完将等待....
}
//发送应答
void SendFunAck(uint16 len)
{
while (Send.start != NO_SEND); //如果上一包数据没发送完将等待....
Send.header.tLen = len;
Send.header.object_addr = LocalAddr; //目的地址=接收到的源地址
Send.header.cmd = Receive.header.cmd;
SendFun();
}
/*
本程序是在中断中转换关键字的,占用CPU时间(中断时间长),但节省空间,对内存不足的系统采用该方式
对于内存大的系统,不在中断中转换关键字,但内存必须是接受数据的2倍,以保证所有数据都是关键字的最坏情况
*/
void isrReceive(void)
{uint8 ch;
ch = (USART1->DR & 0x1FF);
if (Receive.start == RECEIVE_OVER) //整个协议包接收完毕, 如果还没处理丢掉该数据
{
return;
}
if (ch == SEND_HEADER && Receive.start==NO_HEADER)//? {
init_Receive();
Receive.start = RECEIVE_DATA;//已经收到头,开始接收数据
}
else//数据
{
if (Receive.start == RECEIVE_DATA)//已经收到头,开始接收数据
{
Receive.rLen++;
if( Receive.rLen >= (FRAME_HEADER_LEN+RECEIVE_BUFF_SIZE) )//数据缓冲已经用完,仍然没收到完整的数据包
{//说明多半是数据掉包造成的,或者接收到错误的数据长度
init_Receive();//
return;
}
*pRev++=ch;
if(Receive.rLen==4)//协议包总长度收完//if(receive.rLen==FRAME_HEADER_LEN)//头收完
{
Receive.rrLen=Receive.header.tLen;
swp16HL(&Receive.rrLen);//协议包总长度
}
else if(Receive.rLen>4 && Receive.rLen==Receive.rrLen)//数据接收完毕
{
//校验和地址判断不在此函数里判断
Receive.start=RECEIVE_OVER;//整个协议包接收完毕
}
}
}
}
/*
//中断中调用发送
本程序是在中断中转换关键字的,占用CPU时间(中断时间长),但节省空间,对内存不足的系统采用该方式
对于内存大的系统,不在中断中转换关键字,但内存必须是接受数据的2倍,以保证所有数据都是关键字的最坏情况
*/
void isrSend(void)
{
uint8 ch;
if (Send.sLen == 0)//数据发送完毕
{
//PC_RS485Receive_Enable();//切换RS485到接收状态
//这里数据仍然没发送出去,应该判断TC标志,这里用中断实现
USART1_TCirqEnable();//打开串口1发送完毕中断
Send.start = NO_SEND;//发送完毕
USART1_TXEirqUnable(); // disable TX interrupt if nothing to send
//USART1_TCirqUnable();
}
else
{
ch = *pSend;
if (Send.start == START_SEND)//开始发送.还没发送数据
{
USART1->DR = SEND_HEADER; //发送数据头//SBUF = SEND_HEADER; //发送数据头
Send.start = SEND_DATA;
}
else
{
USART1->DR = ch;//SBUF = ch;
pSend++;
Send.sLen--;
}
}
}
/**************************************************************************************
* 函数原型:void USART1_IRQHandler(void)
* 函数功能:串口中断服务程序
* 输入参数:
* 输出参数:
* 函数说明:
**************************************************************************************/
/*----------------------------------------------------------------------------
USART1_IRQHandler
Handles USART1 global interrupt request.
*----------------------------------------------------------------------------*/
//void USART1_IRQHandler(void)
void USART1_IRQFun(void)
{
volatile unsigned int IIR;
IIR = USART1->SR;
if (IIR & USART_FLAG_RXNE)
{
if(Send.start == NO_SEND)//发送完毕//使用CAN芯片做485才做此判断
{
// read interrupt
USART1->SR &= ~USART_FLAG_RXNE; // clear interrupt
isrReceive();
}
}
if( (IIR & USART_FLAG_TXE) && Send.start != NO_SEND )
{
USART1->SR &= ~USART_FLAG_TXE; // clear interrupt//实际对USART_DR的写操作,将该位清零
isrSend();
}
if( (IIR & USART_FLAG_TC)&& Send.start == NO_SEND )
{
USART1->SR &= ~USART_FLAG_TC; // clear interrupt
USART1_TCirqUnable();
PC_RS485Receive_Enable();//切换RS485到接收状态
//isrSend();
}
}
void sendchar (int ch)
{
while (!(USART1->SR & USART_FLAG_TXE));
USART1->DR = (ch & 0x1FF);
//while (!(USART1->SR & USART_FLAG_TC));
}
void DebugSendBuf(uint8* buf, uint32 len)
{uint32 USART1_irq;
USART1_irq=USART1->CR1;//保存串口中断状态
PC_RS485Send_Enable();//如果定义PC_RS485CAN,这里关闭了串口接收中断
#ifdef PC_RS485//只有485芯片才延时,使用CAN芯片不延时
Wait_ms(1);
#endif
USART1_TXEirqUnable();
USART1_TCirqUnable();
while (len)
{
sendchar(*buf++);
len--;
//Watchdog();
}
//恢复串口中断允许
//USART1->CR1 |= (USART1_irq&(USART_FLAG_TXE|USART_FLAG_TC));
USART1->CR1 |= (USART1_irq&(USART_FLAG_TXE | USART_FLAG_TC | USART_FLAG_RXNE));
}
void USART1_InitConfig(uint32 BaudRate)
{USART_InitTypeDef USART_InitStructure;
//USART1->SR &= ~USART_FLAG_TXE; // clear interrupt
//USART1->SR &= ~USART_FLAG_TC; // clear interrupt
USART_InitStructure.USART_BaudRate = BaudRate;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
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;
/* Configure USART1 */
USART_Init(USART1, &USART_InitStructure);
/* Enable USART1 Receive and Transmit interrupts */
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
//USART_ITConfig(USART1, USART_IT_TXE, ENABLE);//发送时才打开
/* Enable the USART1 */
USART_Cmd(USART1, ENABLE);//仿真看到执行这里,TC标志居然被设置为1了,不知道实际在flash中运行是否是这样
USART1->SR &= ~USART_FLAG_TXE; // clear interrupt
USART1->SR &= ~USART_FLAG_TC; // clear interrupt
// /* Configure USART2 */
// USART_Init(USART2, &USART_InitStructure);
// /* Enable USART2 Receive and Transmit interrupts */
// USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
// USART_ITConfig(USART2, USART_IT_TXE, ENABLE);
// /* Enable the USART2 */
// USART_Cmd(USART2, ENABLE);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -