久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 15321|回復: 24
打印 上一主題 下一主題
收起左側

PIC單片機MODBUS總線通信仿真及程序源碼

  [復制鏈接]
跳轉到指定樓層
樓主
ID:152503 發(fā)表于 2016-12-6 10:38 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
一、MODBUS總線通信仿真(主機程序)
說明: 本例運行時,主機向各從機發(fā)送要求返回A/D轉換值的命令碼,在主機
完整接收到從機A/D數(shù)據(jù)后,在液晶上刷新顯示.
二、MODBUS總線通信仿真(從機程序)
說明: 本例運行時,從機接收主機命令,然后將A/D轉換值通過485回發(fā)給主機顯示.


所有資料下載:
PIC單片機MODBUS總線通信仿真.zip (395.9 KB, 下載次數(shù): 271)

主機程序部分預覽:
  1. #define INT8U  unsigned char
  2. #define INT16U unsigned int
  3. #define INT32U unsigned long
  4. #include <pic.h>
  5. #include <stdio.h>
  6. #include "LM041_4BIT.h"
  7. const char* Prompts[17] =
  8. {
  9.   "****************",
  10.   " RS-485  MODBUS ",
  11.   "  TEST PROGRAM  ",
  12.   "****************"
  13. };
  14. volatile INT8U recv_Data[6];           //串口接收數(shù)據(jù)緩沖區(qū)(6字節(jié))
  15. volatile INT8U recv_idx = 0;           //串口接收數(shù)據(jù)緩沖區(qū)索引
  16. volatile INT8U sl_Addr;                //485從機地址
  17. INT8U  LCD_Buffer[16];                 //LCD顯示緩沖            
  18. INT16U CRC;                            //16位CRC校驗結果
  19. //-----------------------------------------------------------------
  20. #define  LED_Recv  RB6                 //主機接收指示燈
  21. #define  LED_Send  RB7                 //主機發(fā)送指示燈
  22. #define  RDE_485   RC5                 //RS485通信控制端
  23. #define  ADC_REQ   65                  //要求從機返回A/D值的自定義命令碼(范圍65~72)
  24. //19200波特率每字符時間為: 1/19200*(1+8+2) ≈  572us
  25. //幀  間: 3.5個字符時間為: 572 * (3.5 + 1) ≈ 2574us
  26. //字節(jié)間: 1.5個字符時間為: 572 * (1.5 + 1) ≈ 1430us
  27. #define FRAME_SPAN  2574                  //相臨幀之間的間隔時間
  28. #define BYTE_SPAN   1430                  //幀內(nèi)字節(jié)之間的間隔時間
  29. bit     b, F_T1, T_BYTE, T_FRAME, Recv_OK;//相關標識位
  30. //-----------------------------------------------------------------
  31. // 宏定義: 發(fā)送一字節(jié)并等待發(fā)送結束
  32. //-----------------------------------------------------------------
  33. #define Send_Byte(x)                  \
  34. {                                     \
  35.     LED_Send = 1; RDE_485 = 1;        \
  36.     TXREG = x; while (TRMT == 0);     \
  37.     __delay_us(9); LED_Send = 0;      \
  38. }

  39. //-----------------------------------------------------------------
  40. // 宏定義: 設置TIMER1的定時初值并設相關標志位
  41. //-----------------------------------------------------------------
  42. #define Set_TIMER1(x)                \
  43. {                                    \
  44.    TMR1H = (65536 - x) >> 8;         \
  45.    TMR1L = (65536 - x) & 0x0F;       \
  46.    TMR1IF = T_BYTE = T_FRAME = 0;    \
  47.    F_T1 = (x == FRAME_SPAN) ? 1 : 0; \
  48.    if (F_T1) recv_idx = 0;           \
  49. }

  50. //-----------------------------------------------------------------
  51. // 串口初始化
  52. //-----------------------------------------------------------------
  53. void Serial_port_init()
  54. {
  55.     SYNC = 0;                            //選擇異步通信模式
  56.     BRGH = 1;                            //選擇高速波特率發(fā)生模式
  57.     TXEN = 1;                            //允許發(fā)送數(shù)據(jù)
  58.     SPBRG = _XTAL_FREQ/16/19200 - 1;     //設置波特率為19200  
  59.     SPEN = 1;                            //串行通信端口打開
  60.     CREN = 1;                            //使能連續(xù)接收串行數(shù)據(jù)
  61. }

  62. //-----------------------------------------------------------------
  63. // 外設初始化(定時器,485等)
  64. //-----------------------------------------------------------------
  65. void Per_Initialize()
  66. {   
  67.     //端口數(shù)據(jù)方向配置
  68.     TRISC7 = TRISC6 = 1; TRISC5 = 0;     //設置連接485的三只引腳的數(shù)據(jù)方向
  69.     TRISB6 = TRISB7 = 0;                 //主機收/發(fā)指示燈引腳設為輸出
  70.     //配置定時器TIMER0
  71.     T0CS = 0;                            //選擇內(nèi)部系統(tǒng)時鐘源
  72.     PSA = 0; PS2 = 1;PS1 = 0; PS0 = 1;   //預分頻器分配給TIMER0,PS:101->64分頻   
  73.     //配置USART
  74.     Serial_port_init();                  //串口初始化
  75.     RDE_485 = 1;                         //允許485發(fā)送(禁止接收)
  76.     //中斷控制
  77.     RCIE = 1;                            //允許串口接收中斷
  78.     TMR1IE = 1;                          //允許TMR1溢出中斷
  79.     PEIE = 1;                            //允許外設中斷(TMR1,USART均為PIC外設)
  80.     GIE = 1;                             //開中斷
  81.     TMR1ON = 1;                          //啟動TIMER1(默認為1:1分頻)
  82. }

  83. //-----------------------------------------------------------------
  84. // CRC16校驗函數(shù) (基于該函數(shù)可得出512字節(jié)的校驗碼表,改用查表法進行校驗)
  85. // 多項式: X ^ 16 + X ^ 15 + X ^ 2 + 1, 去高位逆序表示:0xA001
  86. //-----------------------------------------------------------------
  87. void CRC16(INT8U d)
  88. {













  89. }
  90. //-----------------------------------------------------------------
  91. // 主程序     
  92. //-----------------------------------------------------------------
  93. void main()
  94. {
  95.     INT8U i; INT32U  ADC_Result;
  96.     __delay_ms(100);      //等待足夠時間,待從機完成初始化
  97.     Per_Initialize();     //外設初始化
  98.     LCD_Initialize();     //LCD初始化
  99.     //輸出系統(tǒng)封面文字(4行)
  100.     for (i = 0; i < 4; i++) LCD_ShowString(i,0,(char*)Prompts[i]);
  101.     //延時10*100ms
  102.     i = 10; while (i--) __delay_ms(100);
  103.     ClearScreen();//清屏
  104.     //顯示液晶上兩行文字
  105.     LCD_ShowString(0,0,(char*)"   A/D Display   ");  
  106.     LCD_ShowString(1,0,(char*)"-----------------");
  107.     while(1)
  108.     {  
  109.         //---------------------------------------------------------
  110.         // 循環(huán)訪問地址為0x01~0x04的4個485從機
  111.         //---------------------------------------------------------
  112.         for (sl_Addr = 0x01; sl_Addr <= 0x04; sl_Addr++)
  113.         {   
  114.             LED_Send = 0;               //主機發(fā)送指示燈開
  115.             RDE_485 = 1;                //允許485發(fā)送(禁止接收)
  116.             Send_Byte(sl_Addr);         //(1)發(fā)送從機地址
  117.             Send_Byte(ADC_REQ);         //(2)發(fā)送操作命令碼(要求從機返回A/D值)
  118.             CRC = 0xFFFF;               //CRC校驗復位
  119.             CRC16(sl_Addr);             //當前從機地址校驗
  120.             CRC16(ADC_REQ);             //當前操作命令碼校驗
  121.             Send_Byte(CRC);             //(3)發(fā)送校驗碼低字節(jié)
  122.             Send_Byte(CRC>>8);          //(4)發(fā)送校驗碼高字節(jié)
  123.             Set_TIMER1(FRAME_SPAN);     //用TIMER1控制相鄰幀之間的時間間隔
  124.             Recv_OK = 0;                //先設接收成功標識為假
  125.             RDE_485 = 0;                //允許485接收(禁止發(fā)送)
  126.             //用TIMER0定時器控制接收一部從機數(shù)據(jù)的超時時間為10ms
  127.             TMR0 = (INT8U)(256 - _XTAL_FREQ / 4 / 64 * 0.01);
  128.             T0IF = 0;                   //清除T0中斷標志
  129.             LED_Send = 1;               //主機發(fā)送指示燈關
  130.             //如果主機接收從機數(shù)據(jù)未完成且未超時(10ms)則等待
  131.             while(!Recv_OK && !T0IF);
  132.             //-----------------------------------------------------
  133.             //如果主機接收從數(shù)據(jù)成功則繼續(xù)下面的處理
  134.             if (Recv_OK)
  135.             {   GIE = 0;                //關中斷
  136.                 Recv_OK = 0;            //接收成功標志重設為假
  137.                 CRC = 0xFFFF;           //CRC校驗初始化
  138.                 //對來自當前從機的6字節(jié)數(shù)據(jù)進行CRC校驗
  139.                 for (i = 0; i < 6; i++) CRC16(recv_Data[i]);
  140.                 //校驗通過時顯示
  141.                 if (CRC == 0x0000)
  142.                 {
  143.                     LED_Send = 1;            //主機發(fā)送指示燈關閉
  144.                     //從機發(fā)送的6字節(jié)分別是:站號/命令碼/兩字節(jié)數(shù)據(jù)(模數(shù)值)/兩字節(jié)CRC
  145.                     //recv_Data[2],[3]所保存的是從機返回的模/數(shù)轉換值
  146.                     ADC_Result = (recv_Data[2] << 8) + recv_Data[3];
  147.                     //生成待顯示字符串
  148.                     sprintf(LCD_Buffer,
  149.                        "V%d:%4.2f",sl_Addr,(float)(ADC_Result * 5.0 / 1023.0));
  150.                     //發(fā)送到LCD顯示(顯示LCD的下兩行,每行顯示兩組)
  151.                     LCD_ShowString(
  152.                       (INT8U)(sl_Addr-1)/2+2,(sl_Addr&0x01)?0:9, LCD_Buffer);
  153.                 }
  154.             }
  155.             //每完成一個從機數(shù)據(jù)處理后延時10ms再開中斷
  156.             __delay_ms(10); GIE = 1;
  157.             //-----------------------------------------------------
  158.         }
  159.         __delay_ms(10); //每完成一輪(4個從機)掃描后等待10ms
  160.     }
  161. }

  162. //-----------------------------------------------------------------
  163. // 主機定時中斷及485接收中斷服務程序
  164. //-----------------------------------------------------------------
  165. void interrupt ISR()
  166. {  
  167.     INT8U R;
  168.     //----------------------TIMER1定時器溢出中斷--------------------
  169.     if (TMR1IF)
  170.     {   TMR1IF = 0;
  171.         //F_T1: 標識TIMER1定時器當前用于實現(xiàn)幀間隔時間定時還時字節(jié)間隔時間定時
  172.         //F_T1 = 0時,將幀間隔時間(3.5字符)到達設為假,字節(jié)間隔時間到達設為真
  173.         //F_T1 = 1時,將幀間隔時間(3.5字符)到達設為真,字節(jié)間隔時間到達設為假
  174.         if (F_T1 == 0) { T_FRAME = 0; T_BYTE  = 1; }
  175.         else           { T_FRAME = 1; T_BYTE  = 0; }        
  176.     }
  177.     //-------------------------串口接收中斷-------------------------
  178.     if (RCIF)
  179.     {   
  180.         LED_Recv = ~LED_Recv;                   //主機接收指示燈閃爍
  181.         R = RCREG;                              //從串口(來自485)讀取一字節(jié)
  182.         RCIF = 0;                               //清標志位(此行可省略)
  183.         Recv_OK = 0;                            //先暫時設接收成功標志為假
  184.         //---------------------------------------------------------
  185.         //如果當前要接收的是第0字節(jié)
  186.         if (recv_idx == 0)
  187.         {   //如果幀間時間間隔未到,或所收到的字節(jié)與設備地址不匹配
  188.             //則重新設TIMER1定時長度為幀間時長FRAME_SPAN
  189.             if (T_FRAME == 0 || R != sl_Addr) { Set_TIMER1(FRAME_SPAN); }
  190.             //否則表示接收的第0個字節(jié)與其設備地址匹配
  191.             else
  192.             {   recv_Data[recv_idx++] = R;      //字節(jié)R保存到接收緩沖recv_Data
  193.                 Set_TIMER1(BYTE_SPAN);          //重設T1定時長度為幀內(nèi)字節(jié)間的時長
  194.             }
  195.         }
  196.         //---------------------------------------------------------
  197.         //否則要接收的是第0字節(jié)(即地址字節(jié))之后的數(shù)據(jù)
  198.         else
  199.         {   //如果后續(xù)接收過程中幀內(nèi)字節(jié)時間間隔未超過1.5個字符時間
  200.             if (T_BYTE == 0)
  201.             {   
  202.                 recv_Data[recv_idx++] = R;      //首先將有效字節(jié)保存到接收緩沖
  203.                 //如果接收到的地址字節(jié)(第0字節(jié))后的字節(jié)(即第1字節(jié))不等于操作碼
  204.                 //則將接收緩沖索引歸0,并重設T1定時長度為幀間隔時長
  205.                 //(注意recv_idx == 2時,剛剛保存R是第1字節(jié))
  206.                 if ( recv_idx == 2 && R != ADC_REQ) { Set_TIMER1(FRAME_SPAN); }
  207.                 //如果接收到來自當前從機的完整的6個字節(jié)數(shù)據(jù)
  208.                 else if (recv_idx == 6)
  209.                 {   
  210.                     Set_TIMER1(FRAME_SPAN);     //重設T1定時長度為幀間隔時長
  211.                     Recv_OK = 1;                //設置接收成功標識為真
  212.                 }
  213.                 else { Set_TIMER1(BYTE_SPAN); } //重設T1定時長度為幀內(nèi)字節(jié)間的時長
  214.             }
  215.             //同一幀內(nèi)字符間的時間超時,重設T1為幀之間的時間間隔
  216.             else  { Set_TIMER1(FRAME_SPAN); }
  217.         }
  218.         //---------------------------------------------------------
  219.     }
  220. }</div><div>從機程序:</div><div>#define _XTAL_FREQ 4000000UL
  221. #define INT8U  unsigned char
  222. #define INT16U unsigned int
  223. #define INT32U unsigned long
  224. #include <pic.h>
  225. #include <stdio.h>
  226. //配置字,注意禁用MCLR,因為RA3/MCLR/VPP引腳用于485從機地址次高位輸入
  227. __CONFIG(MCLRDIS & WDTDIS & INTIO);
  228. volatile INT8U recv_Data[4];           //串口接收數(shù)據(jù)緩沖區(qū)(4字節(jié))
  229. volatile INT8U recv_idx = 0;           //串口接收數(shù)據(jù)緩沖區(qū)索引
  230. volatile INT8U sl_Addr;                //485從機地址           
  231. INT16U CRC;                            //16位CRC校驗結果
  232. //-----------------------------------------------------------------
  233. #define  LED_Ptr   RC0                 //本機收/發(fā)指示燈
  234. #define  RDE_485   RC3                 //RS485通信控制端
  235. #define  ADC_REQ   65                  //要求從機返回A/D值的自定義命令碼(范圍65~72)
  236. //19200波特率每字符時間為: 1/19200*(1+8+2) ≈  572us
  237. //幀  間: 3.5個字符時間為: 572 * (3.5 + 1) ≈ 2574us
  238. //字節(jié)間: 1.5個字符時間為: 572 * (1.5 + 1) ≈ 1430us
  239. #define FRAME_SPAN  2574                  //相臨幀之間的間隔時間
  240. #define BYTE_SPAN   1430                  //幀內(nèi)字節(jié)之間的間隔時間
  241. bit     b, F_T1, T_BYTE, T_FRAME, Recv_OK;//相關標識位
  242. INT8U   AD_Result[2];                     //2字節(jié)的A/D轉換結果
  243. //-----------------------------------------------------------------
  244. // 宏定義: 發(fā)送一字節(jié)并等待發(fā)送結束
  245. //-----------------------------------------------------------------
  246. #define Send_Byte(x)                  \
  247. {                                     \
  248.     LED_Ptr = ~LED_Ptr;               \
  249.     RDE_485 = 1;                      \
  250.     TXREG = x; while (TRMT == 0);     \
  251.     __delay_us(9);                    \
  252. }
  253. //-----------------------------------------------------------------
  254. // 宏定義: 設置TIMER1的定時初值并設相關標志位
  255. //-----------------------------------------------------------------
  256. #define Set_TIMER1(x)                 \
  257. {                                     \
  258.    TMR1H = (65536 - x) >> 8;          \
  259.    TMR1L = (65536 - x) & 0x0F;        \
  260.    TMR1IF = T_BYTE = T_FRAME = 0;     \
  261.    F_T1 = (x == FRAME_SPAN) ? 1 : 0;  \
  262.    if (F_T1) recv_idx = 0;            \
  263. }
  264. //-----------------------------------------------------------------
  265. // CRC16校驗函數(shù) (基于該函數(shù)可得出512字節(jié)的校驗碼表,改用查表法進行校驗)
  266. // 多項式: X ^ 16 + X ^ 15 + X ^ 2 + 1, 去高位逆序表示:0xA001
  267. //-----------------------------------------------------------------
  268. void CRC16(INT8U d)
  269. {</div><div>
  270. </div><div>
  271. }
  272. //-----------------------------------------------------------------
  273. // 模/數(shù)轉換函數(shù)
  274. //-----------------------------------------------------------------
  275. void AD_Convert()
  276. {
  277.     __delay_us(10);
  278.     GODONE = 1;                          //啟動轉換
  279.     while (ADIF == 0);                   //等待轉換結束
  280.     ADIF = 0;                            //AD中斷標志清0
  281.     AD_Result[1] = ADRESH;               //保存A/D結果的高字節(jié)
  282.     AD_Result[0] = ADRESL;               //保存A/D結果的低字節(jié)
  283. }
  284. //-----------------------------------------------------------------
  285. // 串口初始化
  286. //-----------------------------------------------------------------
  287. void Serial_port_init()
  288. {
  289.     SYNC = 0;                            //選擇異步通信模式
  290.     BRGH = 1;                            //選擇高速波特率發(fā)生模式
  291.     TXEN = 1;                            //允許發(fā)送數(shù)據(jù)
  292.     SPBRG = _XTAL_FREQ/16/19200 - 1;     //設置波特率為19200  
  293.     SPEN = 1;                            //串行通信端口打開
  294.     CREN = 1;                            //使能連續(xù)接收串行數(shù)據(jù)
  295. }
  296. //-----------------------------------------------------------------
  297. // 外設初始化(定時器,485等)
  298. //-----------------------------------------------------------------
  299. void Per_Initialize()
  300. {   
  301.     GIE = 0;                             //禁止中斷
  302.     TRISC = 0B00110000;                  //設置串行通訊端口及LED指示燈端口方向
  303.     LED_Ptr = 0;                         //收/發(fā)指示燈關閉
  304.     RDE_485 = 1;                         //禁止從機485接收
  305.     PORTA = 0x00;                        //初始化PORTA
  306.     WPUA = 0xFF;                         //使能PORTA相應引腳的弱上拉
  307.     TRISA = 0xFF;                        //PORTA所有引腳全部設為輸入
  308.     ANSEL = 0x01;                        //PORTA的RA0設為模擬輸入
  309.     sl_Addr = (PORTA >> 1) & 0x0F;       //獲取所設置的本機地址
  310.     Serial_port_init();                  //串口初始化  
  311.     OSCCON = 0B01101000;                 //使用默認的4M內(nèi)部振蕩器
  312.     ADCON0 = 0B10000001;                 //選擇0通道,A/D結果右對齊,使能A/D
  313.     ADCON1 = 0B01010000;                 //AD轉換時鐘選擇位ADCS<2:0>=101,選擇FOSC/16   
  314.     RCIE = 1;                            //允許串口接收中斷
  315.     TMR1IE = 1;                          //允許TMR1溢出中斷
  316.     PEIE = 1;                            //允許外設中斷(TMR1,USART均為PIC外設)
  317.     GIE = 1;                             //開中斷
  318.     RDE_485 = 0;                         //允許從機485接收(禁止發(fā)送)   
  319.     TMR1ON = 1;                          //啟動TIMER1(默認為1:1分頻)
  320.     __delay_us(2);
  321.     Set_TIMER1(FRAME_SPAN);              //用TIMER1控制相鄰幀之間的時間間隔
  322.     Recv_OK = 0;                         //初始時三個標識全部設為0
  323. }
  324. //-----------------------------------------------------------------
  325. // 主程序
  326. //-----------------------------------------------------------------   
  327. void main()
  328. {
  329.     Per_Initialize();                    //外設初始化
  330.     while(1)
  331.     {
  332.        //如果本從機已經(jīng)接收到完整的四個字節(jié)數(shù)據(jù)
  333.        if (Recv_OK)
  334.        {
  335.           GIE = 0;                       //關中斷
  336.           Recv_OK = 0;                   //接收成功標志重設為假
  337.          //對待所接收的來自主機的4字節(jié)數(shù)據(jù)進行CRC校驗
  338.           CRC = 0xFFFF;  for(INT8U i = 0; i < 4; i++) CRC16(recv_Data[i]);
  339.           //校驗通過后開始向主機發(fā)送數(shù)據(jù)(6字節(jié):本機地址,操作碼,兩字節(jié)A/D,兩字節(jié)CRC)
  340.           if (CRC == 0x0000)
  341.           {
  342.              RDE_485 = 1;                //允許發(fā)送,禁止接收
  343.              __delay_ms(1);              //延時1ms
  344.              AD_Convert();               //AN0通道進行模/數(shù)轉換
  345.              __delay_ms(1);              //延時1ms               
  346.              Send_Byte(sl_Addr);         //回發(fā)本機地址
  347.              Send_Byte(ADC_REQ);         //回發(fā)A/D請求命令
  348.              Send_Byte(AD_Result[1]);    //回發(fā)A/D轉換結果高字節(jié)
  349.              Send_Byte(AD_Result[0]);    //回發(fā)A/D轉換結果低字節(jié)
  350.              CRC = 0xFFFF;               //先將16位的CRC檢驗變量置為全1
  351.              CRC16(sl_Addr);             //校驗本機地址
  352.              CRC16(ADC_REQ);             //校驗A/D請求命令
  353.              CRC16(AD_Result[1]);        //校驗A/D結果高字節(jié)
  354.              CRC16(AD_Result[0]);        //校驗A/D結果低字節(jié)
  355.              Send_Byte(CRC);             //最后發(fā)送兩字節(jié)的CRC校驗值
  356.              Send_Byte(CRC>>8);
  357.              RDE_485 = 0;                //發(fā)送結束后,再允許本機485接收
  358.           }
  359.           GIE = 1;                       //開中斷
  360.        }
  361.     }
  362. }
  363. //-----------------------------------------------------------------
  364. // 485從機中斷服務程序
  365. //-----------------------------------------------------------------
  366. void interrupt ISR()
  367. {  
  368.     INT8U R;
  369.     //----------------------TIMER1定時器溢出中斷--------------------
  370.     if (TMR1IF)
  371.     {   TMR1IF = 0;
  372.         //F_T1: 標識TIMER1定時器當前用于實現(xiàn)幀間隔時間定時還時字節(jié)間隔時間定時
  373.         //F_T1 = 0時,將幀間隔時間(3.5字符)到達設為假,字節(jié)間隔時間到達設為真
  374.         //F_T1 = 1時,將幀間隔時間(3.5字符)到達設為真,字節(jié)間隔時間到達設為假
  375.         if (F_T1 == 0) { T_FRAME = 0; T_BYTE  = 1; }
  376.         else           { T_FRAME = 1; T_BYTE  = 0; }        
  377.     }
  378.     //-------------------------串口接收中斷-------------------------
  379.     if (RCIF)
  380.     {   
  381.         LED_Ptr = ~LED_Ptr;                     //從機收/發(fā)指示燈閃爍
  382.         R = RCREG;                              //從串口(來自485)讀取一字節(jié)
  383.         RCIF = 0;                               //清標志位(此行可省略)
  384.         Recv_OK = 0;                            //先暫時設接收成功標志為假
  385.         //---------------------------------------------------------
  386.         //如果當前要接收的是第0字節(jié)
  387.         if (recv_idx == 0)
  388.         {   //如果幀間時間間隔未到,或所收到的字節(jié)與設備地址不匹配
  389.             //則重新設TIMER1定時長度為幀間時長FRAME_SPAN
  390.             if (T_FRAME == 0 || R != sl_Addr) { Set_TIMER1(FRAME_SPAN); }
  391.             //否則表示接收的第0個字節(jié)與其設備地址匹配
  392.             else
  393.             {   recv_Data[recv_idx++] = R;      //字節(jié)R保存到接收緩沖
  394.                 Set_TIMER1(BYTE_SPAN);          //重設T1為幀內(nèi)字節(jié)間時長
  395.             }
  396.         }
  397.         //---------------------------------------------------------
  398.         //否則要接收的是第0字節(jié)(即地址字節(jié))之后的數(shù)據(jù)
  399.         else
  400.         {   //如果后續(xù)接收過程中幀內(nèi)字節(jié)時間間隔未超過1.5個字符時間
  401.             if (T_BYTE == 0)
  402.             {   
  403.                 recv_Data[recv_idx++] = R;      //首先將有效字節(jié)保存到接收緩沖
  404.                 //如果接收到的地址字節(jié)(第0字節(jié))后的字節(jié)(即第1字節(jié))不等于操作碼
  405.                 //則將接收緩沖索引歸0,并重設T1定時長度為幀間隔時長
  406.                 //(注意recv_idx == 2時,剛剛保存R是第1字節(jié))
  407.                 if ( recv_idx == 2 && R != ADC_REQ) { Set_TIMER1(FRAME_SPAN); }
  408.                 //如果接收到來自主機的完整的4個字節(jié)數(shù)據(jù):(本機地址,命令碼,兩字節(jié)CRC)
  409.                 else if (recv_idx == 4)
  410.                 {   
  411.                     Set_TIMER1(FRAME_SPAN);     //重設T1定時長度為幀間隔時長
  412.                     Recv_OK = 1;                //設置接收成功標識為真
  413.                 }
  414.                 else { Set_TIMER1(BYTE_SPAN); } //重設T1定時長度為幀內(nèi)字節(jié)間的時長
  415.             }
  416.             //同一幀內(nèi)字符間的時間超時,重設T1為幀之間的時間間隔
  417.             else  { Set_TIMER1(FRAME_SPAN); }
  418.         }
  419.         //---------------------------------------------------------
  420.     }
  421. }
復制代碼

評分

參與人數(shù) 3黑幣 +58 收起 理由
1559705228 + 3 回帖助人的獎勵!
chtyise + 5 贊一個!
admin + 50 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏4 分享淘帖 頂1 踩
回復

使用道具 舉報

沙發(fā)
ID:122531 發(fā)表于 2017-2-19 16:16 | 只看該作者
請問一下樓主,CRC校驗是怎么實現(xiàn)的?
回復

使用道具 舉報

板凳
ID:97308 發(fā)表于 2017-4-20 09:26 | 只看該作者
這個不錯,正需要,謝謝
回復

使用道具 舉報

地板
ID:97308 發(fā)表于 2017-4-20 09:28 | 只看該作者
void CRC16(INT8U d)
{

}
這段程序是空的,要自己找
回復

使用道具 舉報

5#
ID:97308 發(fā)表于 2017-4-20 09:38 | 只看該作者
/*********************************************************************************/  
/*函數(shù)名稱: GetCRC16()                           
*輸入?yún)?shù):  共  個參數(shù);  
*輸出參數(shù):  共  個參數(shù);  
*返回值:   
*需儲存的參數(shù): 共  個參數(shù);      
*功能介紹:   
        (1)CRC16校驗; 返回校驗碼;               
*修改日志:  
*[2005-11-28 16:40]    Ver. 1.00  
        開始編寫;  
        完成;                                      
/*                                      */  
/*********************************************************************************/  
  
unsigned short GetCRC16(unsigned char *puchMsg, unsigned short usDataLen)   
{   
    /* CRC 高位字節(jié)值表 */   
    unsigned char auchCRCHi[256] = {  
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,   
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,   
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,   
    0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,   
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,   
    0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,   
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,   
    0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,   
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,   
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,   
    0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,   
    0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,   
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,   
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,   
    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,   
    0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,   
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,   
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,   
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,   
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,   
    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,   
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,   
    0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,   
    0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,   
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,   
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40  
    };   
      
    unsigned char auchCRCLo[256] = {  
    0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,   
    0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,   
    0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,   
    0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,   
    0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,   
    0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,   
    0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,   
    0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,   
    0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,   
    0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,   
    0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,   
    0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,   
    0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,   
    0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,   
    0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,   
    0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,   
    0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,   
    0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,   
    0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,   
    0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,   
    0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,   
    0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,   
    0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,   
    0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,   
    0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,   
    0x43, 0x83, 0x41, 0x81, 0x80, 0x40  
    };  
      
    unsigned char uchCRCHi = 0xFF ; /* 高CRC字節(jié)初始化 */   
    unsigned char uchCRCLo = 0xFF ; /* 低CRC 字節(jié)初始化 */   
    unsigned uIndex = 0; /* CRC循環(huán)中的索引 */   
      
    while (usDataLen--) /* 傳輸消息緩沖區(qū) */   
    {   
        uIndex = uchCRCHi ^ *puchMsg++ ; /* 計算CRC */   
        uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ;   
        uchCRCLo = auchCRCLo[uIndex] ;   
    }   
    return (unsigned short)((unsigned short)uchCRCHi << 8 | uchCRCLo) ;   
}   
/*****************************************************************************/  
回復

使用道具 舉報

6#
ID:211380 發(fā)表于 2017-6-15 02:37 | 只看該作者
謝謝樓主分享
回復

使用道具 舉報

7#
ID:48413 發(fā)表于 2017-8-7 18:19 | 只看該作者
謝謝共享學習一下
回復

使用道具 舉報

8#
ID:240143 發(fā)表于 2017-10-17 10:05 | 只看該作者
重新編譯后仿真沒顯示呀。請問程序是不是還有問題?
回復

使用道具 舉報

9#
ID:268556 發(fā)表于 2018-1-3 15:49 | 只看該作者
太誘人了,可是我沒有權限不能下載
回復

使用道具 舉報

10#
ID:275802 發(fā)表于 2018-1-14 12:58 | 只看該作者
感謝分享
回復

使用道具 舉報

11#
ID:292657 發(fā)表于 2018-3-16 11:01 | 只看該作者
十分誘人啊!收藏先
回復

使用道具 舉報

12#
ID:161634 發(fā)表于 2018-4-9 17:32 | 只看該作者
贊!!!!!!
回復

使用道具 舉報

13#
ID:302666 發(fā)表于 2018-4-11 20:08 | 只看該作者
版主解釋的很詳細
回復

使用道具 舉報

14#
ID:326624 發(fā)表于 2018-5-10 11:06 | 只看該作者
感謝分享,很詳細
回復

使用道具 舉報

15#
ID:335780 發(fā)表于 2018-5-22 17:08 | 只看該作者
好資料,51黑有你更精彩!!!
回復

使用道具 舉報

16#
ID:249901 發(fā)表于 2018-5-24 20:47 | 只看該作者
樓主玩的可以的!
回復

使用道具 舉報

17#
ID:165117 發(fā)表于 2018-5-27 16:59 | 只看該作者
好資料,51黑有你更精彩!!!
回復

使用道具 舉報

18#
ID:86450 發(fā)表于 2018-8-14 22:55 來自手機 | 只看該作者
zhili 發(fā)表于 2017-4-20 09:28
void CRC16(INT8U d)
{


厲害了,謝謝樓主
回復

使用道具 舉報

19#
ID:388231 發(fā)表于 2018-8-21 10:53 | 只看該作者
學習啦
回復

使用道具 舉報

20#
ID:389439 發(fā)表于 2019-6-21 15:41 | 只看該作者
這個可以有,好好消化一下
回復

使用道具 舉報

21#
ID:48413 發(fā)表于 2019-8-29 20:27 | 只看該作者

謝謝共享學習一下
回復

使用道具 舉報

22#
ID:119977 發(fā)表于 2019-9-16 16:20 | 只看該作者
樓主您這是什么開發(fā)環(huán)境    我也想玩PIC
回復

使用道具 舉報

23#
ID:592524 發(fā)表于 2019-9-26 21:26 | 只看該作者
這個不錯,謝謝。
另外樓主用的是什么編譯器呢?
回復

使用道具 舉報

24#
ID:574127 發(fā)表于 2019-10-8 15:02 | 只看該作者
謝謝共享學習一下
回復

使用道具 舉報

25#
ID:494559 發(fā)表于 2019-12-7 12:43 | 只看該作者
謝謝共享學習一下
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復 返回頂部 返回列表
主站蜘蛛池模板: a久久 | 91九色视频在线 | 黄色在线免费观看视频网站 | 在线免费观看亚洲 | 伊伊综合网 | 国产精品久久久久aaaa樱花 | 欧美婷婷| 国产日韩一区二区三免费高清 | 久久美女网 | 99色在线视频| 玖玖操 | 99精品视频免费在线观看 | av在线免费观看不卡 | 国产精品久久久久久久久免费丝袜 | 国产欧美日韩一区 | 男人天堂网址 | 久久精品一区二区三区四区 | 欧美成视频 | 日本精品久久久一区二区三区 | 在线视频日韩 | 成人综合久久 | 久久久五月天 | 国产精品精品 | 在线观看av网站 | 久久久999国产精品 中文字幕在线精品 | 欧美九九 | 在线一区二区三区 | 男女羞羞视频在线 | 国产伦一区二区三区久久 | 成人不卡 | 欧美操操操 | 人人九九精 | 少妇黄色 | 欧美日韩国产一区二区三区 | 日日操网站 | 欧美午夜影院 | 美女视频久久 | 成人片网址 | 亚洲精品一区二三区不卡 | 夜夜夜久久| 亚洲国产黄色av |