打印

LM3S811心得之二 上下位机串行数据包协议+串12864

[复制链接]
3744|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
dsl1784|  楼主 | 2011-11-19 19:01 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 dsl1784 于 2011-11-19 20:44 编辑

上位机控制下位机的一个协议。先上图。上位机发送数据包指令点亮二极管,下位机点亮LED,并在12864上显示当前状态。或者,上位机发送数据包指令点亮二极管,下位机点亮LED,并在12864上显示当前状态,在串口助手上面显示当前状态。
手机拍的效果不好。源码在最后面有完整的压缩包。大家一起学习了。
12864 用了PA 3 4 5。当然还有要与小3共地。
数据包格式 :
起始字 0x30
命令字 0xa0  参数跟 00 查询此时切换状态
          0xa1  参数    00~07 切换通道命令
参数字
校验码 为命字与参数字的异或
结束字 0x31
例如:打开通道一 输入     0x30 0xa1 01 0xa0 0x31
        查看当前状态 输入  0x30 0xa0 00 0xa0 0x31

下位机收到数据包后的回响包
起始字 0x30
命令接受字 00  正确接受并执行
                01  下发命令字错误
                02  下发参数错误
参数字     当前命令
校验码     为命字与参数字的异或
结束字 0x31

我找了好久,发现这个串口助手最好用。也一并传上来了。 UartAssist_47291.rar (372.99 KB) 串口通信上下位置机协议.rar (568.92 KB)
起始状态

上位机状态

选择通道后

LED
   LCD

#include "systemInit.h"
#include "12864_SE.h"

#define OL3 GPIOPinWrite(GPIO_PORTD_BASE,GPIO_PIN_0,GPIO_PIN_0)
#define OL4 GPIOPinWrite(GPIO_PORTD_BASE,GPIO_PIN_1,GPIO_PIN_1)
#define OL5 GPIOPinWrite(GPIO_PORTB_BASE,GPIO_PIN_0,GPIO_PIN_0)
#define OL6 GPIOPinWrite(GPIO_PORTB_BASE,GPIO_PIN_1,GPIO_PIN_1)
#define OL7 GPIOPinWrite(GPIO_PORTE_BASE,GPIO_PIN_0,GPIO_PIN_0)
#define OL8 GPIOPinWrite(GPIO_PORTE_BASE,GPIO_PIN_1,GPIO_PIN_1)

#define CL3 GPIOPinWrite(GPIO_PORTD_BASE,GPIO_PIN_0,~GPIO_PIN_0)
#define CL4 GPIOPinWrite(GPIO_PORTD_BASE,GPIO_PIN_1,~GPIO_PIN_1)
#define CL5 GPIOPinWrite(GPIO_PORTB_BASE,GPIO_PIN_0,~GPIO_PIN_0)
#define CL6 GPIOPinWrite(GPIO_PORTB_BASE,GPIO_PIN_1,~GPIO_PIN_1)
#define CL7 GPIOPinWrite(GPIO_PORTE_BASE,GPIO_PIN_0,~GPIO_PIN_0)
#define CL8 GPIOPinWrite(GPIO_PORTE_BASE,GPIO_PIN_1,~GPIO_PIN_1)

void CL_ALL()
{
  CL3;CL4;CL5;CL6;CL7;CL8;
}

void light_led(uchar x)
{
   switch(x)
   {
                   case 1:CL_ALL();OL3;break;
                case 2:CL_ALL();OL4;break;
                case 3:CL_ALL();OL5;break;
                case 4:CL_ALL();OL6;break;
                case 5:CL_ALL();OL7;break;
                case 6:CL_ALL();OL8;break;
                default :CL_ALL();
   }
}

#define BEG 0x30         //起始字
#define END 0x31         //结束字
uchar channel = 0;

//   定义接收缓冲区
#define RX_BUF_SIZE  5            //   缓冲区最大限制长度
uchar RxBuf[RX_BUF_SIZE + 1];     //   接收缓冲区
uint  RxIndex = 0;                //   缓冲区位置变量
uchar RxEndFlag = false;                //   接收结束标志

//  定义待发送的数据
#define TX_BUF_SIZE  5              //   缓冲区最大限制长度
uchar TxBuf[TX_BUF_SIZE + 1];         //   发送缓冲区
uint  TxIndex = 0;                                 //   发送冲区位置变量,对于发送数组大于16B的用得上
uchar TxEndFlag = false;                //   发送结束的标志

//  通过UART 发送字符串        缓冲区小于16B用
void uart_puts(const char *s)
{
      while (*s != '\0')
      {
           UARTCharPut(UART0_BASE,*(s++));
      }
}

//  填充发送FIFO (填满FIFO 之后就退出,不会等待,缓冲区大于16用中断法)
void TX_Fill(void)
{
   uchar c;
   for (;;)
   {
         c = TxBuf[TxIndex];
         if (c == '\0')                 //   若填充完毕
         {
               TxEndFlag = true;        //   发送结束标志置位,并跳出
                           TxIndex = 0;
               break;
         }
         if (UARTSpaceAvail(UART0_BASE)) //  若发送FIFO 里有可用空间
         {
               UARTCharPutNonBlocking(UART0_BASE,c);//填充发送FIFO
               TxIndex++;
         }
         else           // 若没有空间则跳出,不必等待
         {
                           break;
         }
   }
}

void RX_Get(void)
{
        uchar d;
    while(UARTCharsAvail(UART0_BASE))//有字符接收
        {
                  d = UARTCharGetNonBlocking(UART0_BASE);//从接收FIFO里读取字符
                 RxBuf[RxIndex] = d;
                 RxIndex++;
         }
         if(RxIndex>=5)
         {
                 RxEndFlag = true;//一次接受完成
                 RxIndex = 0;
         }
}


/*下位机 数据包处理函数*/
void pag_proc()
{
         uchar resp=0;  //回送响应包状态字
         uchar jiaoyan = 0;        //校验字
         if((RxBuf[0]==BEG)&&(RxBuf[4]==END))//起始字 结束字检查
         {
          if((RxBuf[1]^RxBuf[2])==RxBuf[3])//校验字字检查
          {
           switch(RxBuf[1])
           {
                 case 0xa0:
                    if(channel==0)
                   {
                            uart_puts("通道还未设置 ");
                         resp=0x03;
                   }
                   else
                   {
                            uart_puts("当前开启通道为: ");
                         UARTCharPut(UART0_BASE,channel+0x30);
                         write_com(0x01);//清显示
                         delay_nms(5);
                         write_str(2,1,"开启通道为: ");
                         lcd_pos(2,7);
                         write_data(channel+0x30);
                   }
                     break;     //此指令为状态查询 只要将默认状态字写回 无操作
                  case 0xa1:
                     if((RxBuf[2]>0)&&(RxBuf[2]<=7))
                   {
                                   channel = RxBuf[2];//参数传递 通道值
                                uart_puts("设置通道为: ");
                                 UARTCharPut(UART0_BASE,channel+0x30);
                                light_led(channel);//对应操作
                                write_com(0x01);//清显示
                                delay_nms(5);
                            write_str(2,1,"当前通道为:");
                                lcd_pos(2,7);
                                write_data(channel+0x30);
                   }
                   else
                   {
                              resp = 0x01;  //回递输入通道参数错误标示
                           uart_puts("通道设置错误");
                           write_com(0x01);//清显示
                           delay_nms(5);
                           write_str(2,1,"通道设置错误");
                   }
                   break;
                   default: resp = 0x02;  
                                            uart_puts("指令设置错误");
                                          write_com(0x01);//清显示
                                        delay_nms(5);
                                          write_str(2,1,"指令设置错误");
                                           break;//指令错误            
                }
                                jiaoyan = resp^channel;//以下的处理  上位机接收到做出相应操作
                                //回包数据压缩
                                TxBuf[0] = BEG+0x30;
                                TxBuf[1] = resp+0x30;
                                TxBuf[2] = channel+0x30;
                                TxBuf[3] = jiaoyan+0x30;
                                TxBuf[4] = END+0x30;
                                //        TX_Fill();//回送数据包 因为工具关系改为输出字符跃
          }
          else
          {
                 uart_puts("数据丢失");
             write_com(0x01);//清显示
                 delay_nms(5);
                 write_str(2,1,"数据丢失");
          }
   }
   else
   {
                  uart_puts("数据格式错误");
            write_com(0x01);//清显示
                delay_nms(5);
                write_str(2,1,"数据格式错误");
   }
}


void disp_buf(uchar a)
{
         write_data(a/100+0x30);
         write_data(a/10%10+0x30);
         write_data(a%10+0x30);
}                       

int main()
{
        JtagWait();
        clockInit();
        GPIO_init();
        func_init();
        lcd_init();
        uart_puts("串口正常开启");
        while(1)
        {
                RX_Get();//接受数据到缓存
                if(true == RxEndFlag)//有数据数据接受
                {
                           pag_proc();//数据包处理
                        RxEndFlag = 0;
                }
        }
}

#include "12864_SE.h"
/*************************************
12864串行         Volatile
更改各个端口 注意下面初始化也要改
GPIOA 3 4 5口
**************************************/
void write_byte(unsigned char date)
{
unsigned char i=0;
for(i=0;i<8;i++)
    {
    if(date&0x80)
        DI_1;
        else
        DI_0;
        CLK_0;
        delay_nus(1);
        CLK_1;
        delay_nus(12);
        date<<=1;
    }
}
void write_com(unsigned char cmd)
{
    write_byte(0xf8);//写命令控制字
    write_byte(cmd&0xf0);
    cmd<<=4;
    write_byte(cmd&0xf0);
}
void write_data(unsigned char data)
{
    write_byte(0xfa);//写数据控制字
    write_byte(data&0xf0);
    data<<=4;
    write_byte(data&0xf0);
}

/*设定显示位置*/
void lcd_pos(unsigned char X,unsigned char Y)
{
         unsigned char pos;
         if(X==1)
                 {X=0x80;}
         else if(X==2)
                 {X=0x90;}         
         else if(X==3)
                 {X=0x88;}
         else if(X==4)
                 {X=0x98;}
         pos=X+Y-1;
         write_com(pos);//显示地址
}

//=============给定字符串 写入到12864=============
void write_str(unsigned char hang,unsigned char lie,const unsigned char *p)
{
        lcd_pos(hang,lie);
        while(*p!='\0')
        {
                write_data(*p);
                p++;
        }
}

/*LCD初始化设定*/
void lcd_init()
{
          SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
          GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE,GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5);
          CS_ON;//初始化 控制端
          CLK_0;
          write_com(0x30);//基本指令集  扩充指令集0x34
          delay_nms(5);
          write_com(0x0c);//显示开 光标关
          delay_nms(5);
          write_com(0x01);//清显示
          delay_nms(5);
}

起始字错误.jpg (71.32 KB )

起始字错误.jpg

起始字错误.jpg (71.32 KB )

起始字错误.jpg

错误显示.jpg (1.03 MB )

错误显示.jpg

相关帖子

沙发
tianm| | 2011-11-21 16:10 | 只看该作者
不错不错 很详细 很有参考价值 这样的贴子要多发

使用特权

评论回复
板凳
zhongjiehe| | 2012-4-20 10:06 | 只看该作者
值得学习,谢谢····共享。顶

使用特权

评论回复
地板
q12345q| | 2013-1-18 09:58 | 只看该作者
想问下管脚的接法?详细点,新手不懂

使用特权

评论回复
5
雨落沉轩| | 2013-1-18 14:58 | 只看该作者

使用特权

评论回复
6
forgot| | 2013-1-19 09:01 | 只看该作者
可怜的LM3S

使用特权

评论回复
7
lq521815| | 2014-1-16 19:45 | 只看该作者
感谢楼主

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

16

帖子

1

粉丝