?? comm.c
字號:
/**********************************************
公司名稱:
文 件 名:Comm.c
版 本 號:
程序設計:
說 明:串行通信
完成日期:
修改日期:
功能摘要:
***********************************************/
#define _CommV10
#include "includes.h"
#define TX 1
#define RX 0
#define UART_BUF_SIZE 17
#define VAL_ADDR_MAX 0x0d //*pComData表格的長度
#define FUN_DATA_ADDR_FIRST 0x30 //
/*uint8 *pComData[] PROGMEM =
{
&((uint8 *)&Ps)[3], &((uint8 *)&Ps)[2], &((uint8 *)&Ps)[1],&((uint8 *)&Ps)[0],
&((uint8 *)&PtVal)[1], &((uint8 *)&PtVal)[0],
&((uint8 *)&H_Alarm)[1],&((uint8 *)&H_Alarm)[0],
&((uint8 *)&L_Alarm)[1],&((uint8 *)&L_Alarm)[0],
&BaudAndData,
&AddrVal,
&AlarmSwitch,
};*/
uint8 *pComData[] PROGMEM = //測試數據用。
{
&((uint8 *)&Detect_A1)[1],&((uint8 *)&Detect_A1)[0],
&((uint8 *)&Detect_A0)[1],&((uint8 *)&Detect_A0)[0],
&((uint8 *)&Detect_B1)[1],&((uint8 *)&Detect_B1)[0],
&((uint8 *)&Detect_B0)[1],&((uint8 *)&Detect_B0)[0],
&((uint8 *)&Detect_T0)[1],&((uint8 *)&Detect_T0)[0],
&((uint8 *)&Detect_T1)[1],&((uint8 *)&Detect_T1)[0],
};
WAIT_TIME_STRUCT UartOverTime = {1,0};
static uint8 UartReBuf[UART_BUF_SIZE];
static uint8 UartTxBuf[UART_BUF_SIZE];
static OS_Q UartReEvent;
static OS_Q UartTxEvent;
static volatile uchar fTx_done; //重新發送標志
static volatile uchar fRx_start;
void sendbuf(uchar temp);
void Process_Msg(void);
void UART_Init(void);
void Baud_Init(uchar Baud_Reg);
uint CRC16fromByte(uchar Byte, uint CRC16);
uchar ValTab(uint8 com_data_index);
//-------------------------------------------------
SIGNAL (SIG_UART_RECV) //UART接收完成
{
OS_CLOSE_INT();
OSQPost(&UartReEvent,UDR); //向消息隊列發送一則消息UDR=msg,&UartReEvent數據的長度
if (UartOverTime.fGetTime)
{
UartOverTime.fGetTime = 0;
fRx_start = 1;
}
UartOverTime.WaitTime = _20MS;
OS_OPEN_INT();
}
//--------------------------------------------------
SIGNAL (SIG_UART_DATA) //UART寄存器空
{
uint8 msg = 0;
OS_CLOSE_INT();
if (OSQAccept(&UartTxEvent,&msg) == OS_Q_OK //從消息隊列中取出消息
){
UDR = msg; //發送數據
} else {
UCSRB &= ~(1 << UDRIE); //關掉數據寄存器空中斷允許
}
OS_OPEN_INT();
}
//-----------------------------------------
SIGNAL (SIG_UART_TRANS) //UART發送完成
{
OS_CLOSE_INT();
if (OSQQuery(&UartTxEvent) == OS_Q_NO_EMPTY) //OSQQuery;異常處理
{
UCSRB |= (1 << UDRIE); //UDRIE:數據寄存器空中斷使能
}
else
{
fTx_done = 1;
}
OS_OPEN_INT();
}
//----------------------------------------
/************************************************
函 數 名:sendbuf
功能說明:將要發送的數據傳輸到發送緩存中
*************************************************/
void sendbuf(uchar temp)
{
if ((OSQPost(&UartTxEvent,temp) != OS_Q_FULL) && fTx_done)
{
fTx_done = 0; //完成則重新開始
UCSRB |= (1 << UDRIE); //UDRIE:數據寄存器空中斷使能
}
}
//sendbuf:將要發送的數據傳輸到發送緩存中
//設置發送數據的條件
/************************************************
函 數 名:processmsg
功能說明:逐一處理接受緩沖區的字符
*************************************************/
void Process_Msg(void)
{
uchar i;
uchar temp = 0;
static uint CRC16;
static uchar MsgNum = 0;
static struct Msg_Type
{
uchar Addr; //地址
uchar FunID; //命令碼
uchar Data_AddrH; //地址高位
uchar Data_AddrL; //地址低位
uchar DataLenH; //數據長度高位
uchar DataLenL; //數據長度低位
}MsgBuf;
if (OSQAccept(&UartReEvent,&temp) == OS_Q_OK)
{
if (fRx_start)
{
fRx_start = 0;
MsgNum = 0; //包頭同步
}
switch (MsgNum)
{
case 0:
if (temp == AddrVal) //通信地址 ,當地址與本身的地址相同時
{
MsgBuf.Addr = temp; //結構體
CRC16 = CRC16fromByte(temp,0xffff);
MsgNum++;
}
break;
case 1:
if (temp == 0x03 || temp == 0x04) //功能碼,
{
MsgBuf.FunID = temp;
CRC16 = CRC16fromByte(temp,CRC16);
MsgNum++;
}
else
{
MsgNum = 0;
}
break;
case 2:
MsgBuf.Data_AddrH = temp; //數據地址高位
CRC16 = CRC16fromByte(temp,CRC16);
MsgNum++;
break;
case 3:
MsgBuf.Data_AddrL = temp; //數據地址低位
CRC16 = CRC16fromByte(temp,CRC16);
MsgNum++;
break;
case 4:
MsgBuf.DataLenH = temp; //數據長度高位
CRC16 = CRC16fromByte(temp,CRC16);
MsgNum++;
break;
case 5:
MsgBuf.DataLenL = temp; //數據長度低位
CRC16 = CRC16fromByte(temp,CRC16);
MsgNum++;
break;
case 6:
if (((uchar *)&CRC16)[LOW_BYTE] == temp) //CRC校驗值低位
{
MsgNum++;
}
else
{
MsgNum = 0;
}
break;
case 7:
if (((uchar *)&CRC16)[HIGH_BYTE] == temp) //CRC校驗值高位
{
sendbuf(MsgBuf.Addr); //通信地址
CRC16 = CRC16fromByte(MsgBuf.Addr,0xffff);
sendbuf(MsgBuf.FunID); //功能碼
CRC16 = CRC16fromByte(MsgBuf.FunID,CRC16);
//數據長度
MsgBuf.DataLenL <<= 1; //數據字節數,發過來的是字數 ,回的是字節數
sendbuf(MsgBuf.DataLenL);
CRC16 = CRC16fromByte(MsgBuf.DataLenL,CRC16);//CRC校驗值
for (i=0; i<MsgBuf.DataLenL; i++)
{
sendbuf(ValTab(MsgBuf.Data_AddrL));
CRC16 = CRC16fromByte(ValTab(MsgBuf.Data_AddrL),CRC16);
MsgBuf.Data_AddrL++;
}
sendbuf(((uchar *)&CRC16)[LOW_BYTE]); //發送CRC校驗值
sendbuf(((uchar *)&CRC16)[HIGH_BYTE]);
}
MsgNum = 0;
break;
default:
MsgNum = 0;
break;
}
}
}
//-------------------------------------------------
/************************************************
函 數 名:UART_Init
功能說明:串行口初始化
*************************************************/
void UART_Init(void)
{
OS_Q *pq;
Baud_Init(BaudAndData);
UCSRA = 0;
UCSRB |= (1 << RXCIE)|(1 << TXCIE)|(1 << RXEN)|(1 << TXEN); //允許發送和接收
UCSRC |= (1 << URSEL)|(1 << UCSZ1)|(1 << UCSZ0); //8位數據位+1位停止位
pq = OSQCreat(&UartReEvent,UartReBuf,UART_BUF_SIZE - 1);
UartReEvent = *pq;
pq = OSQCreat(&UartTxEvent,UartTxBuf,UART_BUF_SIZE - 1);
UartTxEvent = *pq;
fTx_done = 1;
fRx_start = 0;
}
/*************************************************************************************
**功 能 描 述:單個字節CRC16校驗
**輸出:2個字節的CRC校驗值
*************************************************************************************/
uint CRC16fromByte(uchar Byte, uint crc16)
{
uchar j;
uchar CY;
crc16 ^= Byte;
for(j=8; j>0; j--)
{
CY = crc16;
CY &= (1 << 0);
crc16 >>= 1;
crc16 &= 0x7fff;
if(CY)
{
crc16 ^= 0xa001;
}
}
return crc16;
}
/************************************************
函 數 名:initi_serial
功能說明:串行口初始化
*************************************************/
uchar ValTab(uint8 com_data_index)
{
uint8 *pReadComData;
//FUN_DATA_ADDR_FIRST 0x30
if (com_data_index >= FUN_DATA_ADDR_FIRST) //VAL_ADDR_MAX 0x0b
{
com_data_index = com_data_index - FUN_DATA_ADDR_FIRST + VAL_ADDR_MAX + 1; //超出范圍則讀不到數據
}
pReadComData = (uint8 *)pgm_read_word(&pComData[com_data_index]);
return (*pReadComData);
}
//ValTab:根據所要得到的變量地址,查表得到具體的數值
//-----------------------------------------------
void Baud_Init(uchar Baud_Reg)
{
if ((Baud_Reg & 0x10) == 0x00)
{
UBRRL = (F_CPU / 16 / (4800+1)) % 256;
UBRRH = (F_CPU / 16 / (4800+1)) / 256; //設置波特率發生器
}
else if ((Baud_Reg & 0x10) == 0x10)
{
UBRRL = (F_CPU / 16 / (9600+1)) % 256;
UBRRH = (F_CPU / 16 / (9600+1)) / 256; //設置波特率發生器
}
}
//------------------------------------------------
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -