⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 comm.c

📁 cs5460a做功率表用 cs5460a做功率表用 cs5460a做功率表
💻 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 + -