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

📄 main.c

📁 带使能端的RS485(SN65HVD3082ED)基于MSP430FE427单片机的串口通讯接受和发送c程序.以通过调试
💻 C
字号:
//#include "msp430x41x.h"//"msp430xE42x.h"
#define uchar  unsigned char
#define uint   unsigned int

#include "msp430xE42x.h"
#include "LCD.h"

#define ENABLE BIT0
#define UTXD   BIT4 
#define URXD   BIT5
#define Num 64

uchar ss[10]={char_0,char_1,char_2,char_3,char_4,char_5,char_6,char_7,char_8,char_9};
uint r0 = 0,s0 = 0,rr0 = 0,aa = 0;
uchar RXFLG = 0,TXFLG = 0,CS = 0x00,SS = 0x00,ACC,CY = 1,Command_Status1 = 0x00;
uchar r_buf[Num],s_buf[Num],a[Num];
/*******************************************************************************
Rec_Judge()
接受数据的判断函数  判断是否符合645协议  并验证效验码
*******************************************************************************/
uchar Rec_Judge(uchar *s)
{
   uchar i,j,k;
   if((*s != 0x68) && (*(s+7) != 0x68)) 
     return 0;
   else
   {
      for(i=1;i<7;i++)
      {
         if(*(s+i) > 0x99)
           return 0;
      }
   }
   if(*(s+9) > (Num-12))
      return 0;
   for(k=0;k<(*(s+9)+10);k++)
   {
      CS += *(s+k);
   }
   for(j=0;j<*(s+9);j++)
   {
      *(s+10+j) -= 0x33;
   }
   if(CS != *(s+(*(s+9)+10)))
     return 0;
   if(*(s+(*(s+9)+11)) != 0x16)
     return 0;
   else
     return 1;
}

/*******************************************************************************
Send_Set()
数据发送的准备函数  把所发送的数据存到s_buf[N]数组中,完成后关节后关闭接受中断,
打开发送中断
*******************************************************************************/
void Send_Set(uchar *s)
{
   uint ii,jj,kk; 
   for(ii=0;ii<4;ii++)      //前导字节
   {
      s_buf[ii] = 0xFE;
      aa += 1;
   }
   for(jj=0;jj<10;jj++)    //帧起始符到数据长度
   {
      s_buf[4+jj] = *(s+jj);
      aa += 1;
      SS += s_buf[4+jj];
   }
   for(kk=0;kk<*(s+9);kk++)    // 数据域的处理和准备
   {
     s_buf[14+kk] = (*(s+10+kk) + 0x33);
     aa += 1;
     SS += s_buf[14+kk];
   }
   aa ++;
   s_buf[(14+s_buf[13])] = SS;    //效验码的计算结果
   aa ++;
   s_buf[(15+s_buf[13])] = 0x16;   //帧结束符
   P2OUT |= ENABLE;
   P2OUT |= URXD;
   IE1 &= ~URXIE0;                  //关接受中断
   IE1 |= UTXIE0;                   //开发送中断
   CY = 1;
}

/*******************************************************************************
delay()
延时函数
*******************************************************************************/
void delay(uint n)
{
    while(n -->0);
}

/*******************************************************************************
Serial_Address()
通讯地址判断函数
*******************************************************************************/
uchar Serial_Address(uchar *s1)
{
   uchar i,a[6];
   for(i=0;i<=5;i++)
   {
      if((*(s_buf+i)) != 0x99)  //不是广播地址
      break; 
      if(i==5)
      return(0x01);
   }
   for(i=0;i<=5;i++)
   {
      if((*(s1+i)) != a[i])
      return(0x00);             //地址不相同
   }
   return(0x02);
}

/*******************************************************************************
Serial_Password()
通讯密码判断函数
*******************************************************************************/
char Serial_Password(uchar *s1)
{
   uchar i,a[4];
   for(i=0;i<=3;i++)
   {
      if((*(s1+i)) != a[i])
      return 0;
   }
   return 1;
}

/*******************************************************************************
Serial_Command_Run()
通讯执行函数
*******************************************************************************/
char Serial_Command_Run(uchar *s)
{
   switch(Serial_Address(s))   //判断地址是否正确
   {
      case 0x02:               //广播地址999999999999H
      break;
      case 0x01: 
      switch(*(s_buf+6))       //正常地址
      {
         case 0x0f:            //进行密码修改
         if(~Serial_Password(s+8))
         return 0;
         delay(5);
         (*(s+6)) |= 0x80;
         (*(s+7)) = 0x04; 
         Send_Set(s);  //*存取新密码
         break;
         case 0x02:

         break;
         case 0x04: 
         break;
         default:
         break;
      }
      break;
      case 0x00:
      return 0;
   }
   return 1;
}

/*******************************************************************************
Serial_Command()
通讯主函数
*******************************************************************************/
void Serial_Command()
{
   if(RXFLG)   //  准备发送数据
   {
      RXFLG = 0;
      TXFLG = Rec_Judge(r_buf);
      if(TXFLG)
      { 
         TXFLG = 0;
         CS = 0x00;
         Command_Status1 |= 0x04;
         if(CY == 1)
         {
            Send_Set(r_buf);
         }
      }
   }
   if(Command_Status1 & 0x04)         //通讯事件发送
   {
      if(~Serial_Command_Run(s_buf))  //帧执行
      {
         Command_Status1 &= 0xfb;     //帧错误,恢复信道功
         return;
      } 
      Command_Status1 &= 0xfb;        //清除通讯处理事件
   }
}

/*******************************************************************************
Init_USART0()
串口初始化函数 
*******************************************************************************/
void Init_USART0(void)
{
   U0CTL |= (SWRST + PENA + PEV + CHAR); //选择偶校验,8位传送
   U0TCTL |= SSEL0; //选择ACLK
   ME1 |= (URXE0 + UTXE0);   //使能UART0的URXD和UTXD
   
   
   P2SEL |= URXD + UTXD +ENABLE; //设置P2.5为URXD,P2.4为UTXD,P2.0为使能端
   P2DIR |= UTXD + ENABLE;  //UTXD和ENABLE置输出
   
   
   U0BR0 = 0x1B; //波特率1200bps
   U0BR1 = 0x00; 
   U0MCTL = 0x03;
   
   TXBUF0 = 0x00;
   U0CTL &= ~SWRST;
   P2OUT &= ~ENABLE;
   IE1 |= URXIE0;  //打开UART0的RX中断
   return;
}

/*******************************************************************************
main()
主函数
*******************************************************************************/
void main(void)
{
   uchar i;
   WDTCTL = WDTPW + WDTHOLD;   //关看门狗
   _DINT();                    //关总中断
   BTCTL = BTHOLD + BTFRFQ1;   
   LCDCTL = LCDON + LCD4MUX + LCDSG0_3;
   U0IFG &= ~URXIFG0;      //复位操作
   U0IFG &= ~UTXIFG0;
   U0CTL = 0X00;
   U0TCTL = 0X00;
   for(i = 0;i < 12;i ++) 
   {
      LCDMEM[i] = 0x00;
   }
   Init_USART0();
   _EINT();             //开总中断
   while(1)
   { 
      Serial_Command();
   }
}

/*******************************************************************************
usart0_rx()
接受中断函数
*******************************************************************************/
uchar Lead_Flag = 0; //前导字节接受标志
uchar Begin_Flag = 0;//开始接收数据帧的标志

#pragma vector=UART0RX_VECTOR
__interrupt void usart0_rx(void)
{
   IFG1 &= ~URXIFG0;
   if(RXBUF0 == 0xfe)
   {
      Lead_Flag ++;
   }
   if((RXBUF0 != 0xfe) && (Lead_Flag > 3))
   {
      Begin_Flag = 1;
   }
   if(Begin_Flag)
   {
      r_buf[r0 ++] = RXBUF0;
      if(r0 >= 10)
      {
         ACC = r_buf[9];
         r_buf[9+rr0] = RXBUF0;
         rr0 ++;
         if(rr0>(ACC+2))
         { 
            r0 = 0;
            rr0 = 0;
            ACC = 0;
            RXFLG = 1;
            Lead_Flag = 0;   
            Begin_Flag = 0;
         }
      } 
   }
}

/*******************************************************************************
usart_tx()
发送中断函数
*******************************************************************************/
#pragma vector=UART0TX_VECTOR
__interrupt void usart0_tx(void)
{
   IFG1 &= ~UTXIFG0;     //清零
   TXBUF0 = s_buf[s0++]; //发送数据到缓冲寄存器
   if(s0 >= aa)          //发送接受的标志
   {
      s0 = 0;
      aa = 0;
      SS = 0;
      P2OUT &= ~ENABLE;  //恢复485使能端置低
      IE1 &= ~UTXIE0;   //关闭发送中断
      IE1 |= URXIE0;    //打开接受中断
   }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -