📄 comm.c
字号:
#define COMM_GLOBALES 1
#include "comm.h"
#include "InitDev.h"
#include "uart0.h"
#include "uart1.h"
#include "driver.h"
#include "I2cInt.h"
//******************有关UART通讯协议,使用前有关设置*******************************
//#define M128_EN1 PORTD |= (1<<7) //少了多路串口使能
//#define M128_DIS1 PORTD &= (~(1<<7))
//*******************其它宏定义******************************************/
/*定义数据缓冲区结构体*/
//*******初始化发送与接收缓冲区,并构缓冲区环型链表
/****************************************************************************
* 名称: buf_init()
* 功能:初始化发送与接收缓冲区
* 入口参数:无
* 出口参数:无
****************************************************************************/
void buf_init(void) //数据缓冲区
{
unsigned char i;
for ( i=0; i<UART_TOL; i++ )
{
TXD_BUF[i].command = 0;
TXD_BUF[i].length = 0;
TXD_BUF[i].sum = 0;
TXD_BUF[i].state = SET_NEW;
}
for ( i=0; i<UART_TOL; i++ )
{
RXD_BUF[i].command = 0;
RXD_BUF[i].length = 0;
RXD_BUF[i].sum = 0;
RXD_BUF[i].state = 0;
}
}
/****************************************************************************
* 名称:UART0_Ini()
* 功能:初始化串口0。设置其工作模式及波特率。
* 入口参数:baud 波特率
datab; 字长度,5/6/7/8
stopb; 停止位,1/2
parity; 奇偶校验位,0为无校验,1奇数校验,2为偶数校验
*
* 出口参数:返回值为1时表示初化成功,为0表除参数出错
****************************************************************************/
uint8 UART0_Ini(uint32 baud, uint8 datab, uint8 stopb, uint8 parity )
{
uint8 bak;
/* 参数过滤 */
if( (0==baud)||(baud>115200) ) return(0);
if( (datab<5)||(datab>8) ) return(0);
if( (0==stopb)||(stopb>2) ) return(0);
if( parity>4 ) return(0);
/* 设置串口波特率 */
U0LCR = 0x80; // DLAB位置1
bak = (uint8)((Fpclk>>4)/baud);
U0DLM = bak>>8;
U0DLL = bak&0xff;
/* 设置串口模式 */
bak = datab-5; // 设置字长度
if(2==stopb) bak |= 0x04; // 判断是否为2位停止位
if(0!= parity) {parity = parity-1; bak |= 0x08;}
bak |= parity<<4; // 设置奇偶校验
U0LCR = bak & 0x7f;
PINSEL0 |= ((1<<0) | (1<<2) ); //设置I/O连接到UART0(RXD0,TXD0)
// 使能FIFO,并设置触发点为1字节
U0FCR = 0x07; // 使能FIFO,并设置触发点为1字节
U0IER = 0x03; // 允许RBR中断与THR中断,即接收中断
/* */
return(1);
}
/****************************************************************************
* 名称:InitComm()
* 功能:初始化缓冲区和串口0。
* 入口参数:无
*
* 出口参数:无
****************************************************************************/
void InitComm ( void )
{
/*初始化数据缓冲区*/
buf_init();
/* UART0_Ini(19200, 8,1,0); // 初始化串口模式,8位数据位,1位停止位,无奇偶校验*/
UART0_Init(19200);
}
/****************************************************************************
* 名称:send_UDR ( );
* 功能:发送单字节数据到相应的串口号
* 入口参数: uart_num 发送串口号
* wait_UDR 等待发送的数据
* 出口参数:无
****************************************************************************/
void send_UDR ( uint8 uart_num, uint8 wait_UDR ) //发送数据
{
switch(uart_num)
{
case 0:
U0THR = wait_UDR;
break;
case 1:
U1THR = wait_UDR;
break;
default:
break;
}
}
//*************发送中断函数,其可以自动把数据缓冲区的数通过UART发送出去
//每次有一个数据缓冲区有新的数据报来发送时,只需调用函数 uart0_tx_isr();一次就可以
//之后,系统将自动发送所有数据报的数据
//数据发送完后,TXD_BUF[0].state的第0位会置1
/****************************************************************************
* 名称:uart_tx_isr()
* 功能:发送中断函数处理函数,自动把数据通过UART发送出去
* 入口参数:uart_num 发送中断所处理的串口号
* 出口参数:无
****************************************************************************/
void uart_tx_isr(uint8 uart_num)
{
/* */
static uint8 dataLen[UART_TOL]; //协商数据长度
static uint8 data_index[UART_TOL];
static uint8 com_index[UART_TOL]; //起动标志位
static struct DATA_BUF *txd_pk[UART_TOL]; //调用数据缓冲区0
static unsigned char StartFlag = FALSE;
unsigned char WAIT_UDR; //定义等待发送变量
unsigned char i =0 ;
if( StartFlag != TRUE )
{
for(i=0; i<UART_TOL; i++)
{
dataLen[i] = 0;
data_index[i] = 0;
com_index[i] = 0;
txd_pk[i] = &TXD_BUF[i];
}
StartFlag = TRUE;
}
if( com_index[uart_num] <= 4)
{
IO0SET=0x00400000;
switch ( com_index[uart_num] )
{
case 0 :
WAIT_UDR = UART_START0; //暂存启动一个数据报发送,第一个字头,0x55
break;
case 1 :
WAIT_UDR = UART_START1; //暂存启动一个数据报发送,第二个字头,0xAA
break;
case 2 :
WAIT_UDR = txd_pk[uart_num]->IP_addr; //暂存通讯设备的IP地址
break;
case 3 :
WAIT_UDR = 0x00; //先清空标志位,主机发送数据永远是对的
//WAIT_UDR |= (txd_pk[uart_num]->state & GET_ERROR); //写帧状态接收正确否
WAIT_UDR |= (txd_pk[uart_num]->length & GET_LEN); //设置发送帧的数据长度0~0x3f
dataLen[uart_num] = txd_pk[uart_num]->length; //暂存数据长度
break;
case 4 :
WAIT_UDR = txd_pk[uart_num]->command; //暂存发送命令
break;
}
com_index[uart_num]++; //命令索引加一
send_UDR ( uart_num, WAIT_UDR ); //发送数据
}
else if ( data_index[uart_num] < dataLen[uart_num] && data_index[uart_num] < DATA_BUF_NUM) //发送帧的数据
{
WAIT_UDR = txd_pk[uart_num]->data[data_index[uart_num]]; //暂存UART发送数据
data_index[uart_num]++; //数据索引加一
send_UDR ( uart_num, WAIT_UDR ); //发送数据
}
else if (data_index[uart_num] <= dataLen[uart_num] ) //发送校验和
{
WAIT_UDR = txd_pk[uart_num]->sum;
data_index[uart_num]++;
send_UDR ( uart_num ,WAIT_UDR ); //发送数据
}
else
{
data_index[uart_num] = 0; //数据与命令索引复位
com_index[uart_num] = 0;
txd_pk[uart_num]->state = txd_pk[uart_num]->state |= SET_NEW; //又有一个新的缓冲区,数据发送完毕
IO0CLR=0x00400000;
}
}
//接收中断函数,其可以自动把接收到的数据报存放在数据缓冲区
//******如果成功接收到一个帧,并把RXD_BUF->state的第0位置1,
/****************************************************************************
* 名称:uart_rx_isr()
* 功能:接收中断函数处理函数,把接收到的数据存贮在缓冲区
* 入口参数:uart_num 发送中断所处理的串口号
uart_UDR 相应串口号接收的数据
* 出口参数:无
****************************************************************************/
void uart_rx_isr(uint8 uart_num,uint8 uart_UDR)
{
//uart has received a character in UDR
//uart has received a character in UDR
/*测试段程序*/
/*接受上位机指令并从串口1发出*/
static uint8 start_flag[UART_TOL] ; //起动标志位
static uint8 dataLen[UART_TOL]; //协商数据长度
static uint8 data_index[UART_TOL]; //数据索引定义
static uint8 com_index[UART_TOL]; //命令索引定义
static struct DATA_BUF *rxd_pk[UART_TOL]; //缓冲区指针定义
static uint8 temp_char1[UART_TOL]; //临时暂存定义
static uint8 temp_char0[UART_TOL];
static uint8 StartFlag = FALSE;
uint8 i;
//数据初始化
if(StartFlag != TRUE)
{
for(i=0; i<UART_TOL; i++)
{
start_flag[i] = 0;
dataLen[i] = 0;
data_index[i] = 0;
com_index[i] = 0;
rxd_pk[i] = &RXD_BUF[i];
temp_char1[i] = 0;
temp_char0[i] = 0;
}
StartFlag = TRUE;
}
temp_char1[uart_num] = uart_UDR; //UART接收数据暂存
if(start_flag[uart_num] == RXD_WAIT) //等待起动
{
if( temp_char1[uart_num] == UART_START1 ) //抗一定的干拢,判断是不是帧启动的第二字节,0XAA
{
if(temp_char0[uart_num] == UART_START0) //判断是不是帧启动的第一字节,0X55
{
start_flag[uart_num] = !RXD_WAIT; //表示一个数据包传送开始
data_index[uart_num] = 0; //数据索引复位
com_index[uart_num] = 0; //命令索引复位
}
}
else
temp_char0[uart_num] = temp_char1[uart_num];//暂存此数据
}
else if( com_index[uart_num] <3) //开始接收命令数据
{
switch(com_index[uart_num])
{
case 0 : //第0个数据,读取IP地址、LEN、STATE
if (IP_ADDR != temp_char1[uart_num]) //判断IP地址是否符合,
start_flag[uart_num] = RXD_WAIT; //如果不符合,从新进入等待自己的数据帧
break;
case 1 :
rxd_pk[uart_num]->length = temp_char1[uart_num] & GET_LEN; //提取数据帧长度,范围0~63
dataLen[uart_num] = rxd_pk[uart_num]->length; //因为数据索引初始就是3
rxd_pk[uart_num]->state &= ~GET_ERROR; //先清空标志位
rxd_pk[uart_num]->state |= (temp_char1[uart_num] & GET_ERROR); //提取整个帧状态
break;
case 2 :
rxd_pk[uart_num]->command = temp_char1[uart_num]; //第2个数据,读取命令字
break;
}
com_index[uart_num]++; //命令索引加一
}
//开始接收帧的数据
else if ( data_index[uart_num] < dataLen[uart_num] && data_index[uart_num] < DATA_BUF_NUM)
{
rxd_pk[uart_num]->data[data_index[uart_num]] //存储数据
= temp_char1[uart_num];
data_index[uart_num] ++;
/**/
//数据索引加一
}
else
{
rxd_pk[uart_num]->sum = temp_char1[uart_num]; //读取校验和
com_index[uart_num] = 0; //命令索引与数据索引复位
data_index[uart_num] = 0;
start_flag[uart_num] = RXD_WAIT; //重启,等待下一新帧
rxd_pk[uart_num]->state |= SET_NEW; //有一个新帧到达,等待执行
}
/* if( ((RXD_BUF[0].state)&SET_NEW)==0x01)
{
perform_command (&RXD_BUF[0]);
}
*/
}
/****************************************************************************
* 名称:set_sum ()
* 功能:设置帧的校验和
* 入口参数:set_pk 需要设置校验和的缓冲区
* 出口参数:无
****************************************************************************/
void set_sum (struct DATA_BUF *set_pk) //设置校验和
{
unsigned char num_sum;
unsigned char i;
num_sum = UART_START0 +UART_START1; //帧头相加
num_sum += set_pk->IP_addr; //加上接收IP地址
num_sum += set_pk->length&GET_LEN
+ (set_pk->state&GET_ERROR); //数据长度与标志位数据
num_sum += set_pk->command; //加上命令
for(i=0; i<set_pk->length; i++) //加上数据
num_sum += set_pk->data[i];
set_pk->sum = num_sum; //设置校验和
}
/****************************************************************************
* 名称:check_sum ()
* 功能:检查校验和正确否
* 入口参数:check_pk 检查校验和正确否的缓冲区
* 出口参数:返回值为1时表示校验和正确,为0表示校验和错误
****************************************************************************/
unsigned char check_sum (struct DATA_BUF *check_pk) //检查校验和
{
unsigned char num_sum;
unsigned char i;
num_sum = UART_START0 +UART_START1; //帧头相加
num_sum += check_pk->IP_addr; //加上接收IP地址
num_sum += check_pk->length&GET_LEN
+ (check_pk->state&GET_ERROR); //数据长度与标志位数据
num_sum += check_pk->command; //加上命令
for(i=0; i<check_pk->length; i++) //加上数据
num_sum += check_pk->data[i];
if ( check_pk->sum == num_sum ) //检查对错
return TRUE;
else
return FALSE;
}
/****************************************************************************
* 名称:send_same_back_uart()
* 功能:用于正确帧的原样返回发送
* 入口参数:uart_num 要返回的串口号
rxd_pk 需要同样返馈的数据缓冲区
* 出口参数:无
****************************************************************************/
void send_same_back_uart(uint8 uart_num,struct DATA_BUF *rxd_pk)
{
struct DATA_BUF *send_pk = &TXD_BUF[uart_num]; //初始化定义
while(!(send_pk->state & SET_NEW)); //等待上一个数据帧发送完毕
send_pk->IP_addr = 0x01; //设置发送从机的IP地址
send_pk->command = rxd_pk->command; //设置反回发送命令,
send_pk->length = 0; //设置帧长为0
send_pk->state &= ~GET_ERROR; //设置错误标志位,无
set_sum (send_pk); //设置校验和
uart_tx_isr(uart_num); //开始发送数据
}
/****************************************************************************
* 名称:send_error_back_uart()
* 功能:用于错误帧的返馈发送
* 入口参数:uart_num 要反馈数据的串口号
rxd_pk 需要同样返馈的数据缓冲区
* 出口参数:无
****************************************************************************/
void send_error_back_uart(uint8 uart_num,struct DATA_BUF *rxd_pk)
{
struct DATA_BUF *send_pk = &TXD_BUF[uart_num]; //初始化定义
while(!(send_pk->state & SET_NEW)); //等待上一个数据帧发送完毕
send_pk->IP_addr = 0x01; //设置发送从机的IP地址
send_pk->command = rxd_pk->command; //设置反回发送命令,
send_pk->length = 0; //设置帧长为0
send_pk->state |= GET_ERROR; //设置错误标志位,有
set_sum (send_pk); //设置校验和
uart_tx_isr(uart_num); //开始发送数据
}
/****************************************************************************
* 名称:IRQ_UART0()
* 功能:串口UART0接收中断。
* 入口参数:无
* 出口参数:无
****************************************************************************/
void __irq IRQ_UART0(void) //与总线通讯串口控制
{
uint8 TempU0RBR;
uint8 TempU0LSR;
uint8 TempU0IIR;
TempU0LSR = U0LSR;
TempU0IIR = U0IIR;
if( (1<<0) == (TempU0LSR&(1<<0)) ) //判断是否是接收中断
{
TempU0RBR = U0RBR;
if(transMode==0)
{
uart_rx_isr(0,TempU0RBR);
}
else
{
if(TempU0RBR==0)
{
transMode=0;
VICVectAddr = 0x00000000;
return;
}
Transparent(TempU0RBR);
}
//进行协议解协
}
else if( (1<<5) == (TempU0LSR&(1<<5)) ) //判断是否是发送中断
{
uart_tx_isr(0);
}
VICVectAddr = 0x00000000; // 中断处理结束
}
/****************************************************************************
* 名称:IRQ_UART1()
* 功能:串口UART1接收中断。
* 入口参数:无
* 出口参数:无
****************************************************************************/
void __irq IRQ_UART1()
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -