[程序源码] 单片机开发10年,单片机例程从易到难连载分享

[复制链接]
35671|172
denglisong149 发表于 2015-4-13 20:31 | 显示全部楼层
吴鉴鹰 发表于 2015-4-7 14:24
第一讲:一个电子工程师当小心为重——吴鉴鹰最近因为意志蜘蛛引发的惨重后果
少了一个铁钉,丢了一只马掌 ...

向楼主学习
pass1876 发表于 2015-4-13 22:10 | 显示全部楼层
写的很好,支持下楼主
 楼主| 吴鉴鹰 发表于 2015-4-14 11:20 | 显示全部楼层
pass1876 发表于 2015-4-13 22:10
写的很好,支持下楼主

谢谢支持,互相学习,共同进步。
 楼主| 吴鉴鹰 发表于 2015-4-14 11:22 | 显示全部楼层
吴鉴鹰 发表于 2015-4-7 14:33
第二讲:【愚人节特别奉献】今天被自己愚弄了一把,一个粗心大意引发的BUG,细节决定成败

导读今天吴鉴鹰 ...

如果程序上万行,怎么看,这是程序量小,很容易看出来。;P
 楼主| 吴鉴鹰 发表于 2015-4-14 16:43 | 显示全部楼层
本帖最后由 吴鉴鹰 于 2015-5-22 17:31 编辑

第四讲:基于单片机的Modbus通讯程序设计(一)


  1. /******************************************************
  2. ** 作品:吴鉴鹰单片机项目之基于Modbus协议的通讯程序                                                                 
  3. ** 申明:转载请标明作品来源 知识产权归作者本人所有!
  4. ** 这一讲的主要内容: 吴鉴鹰单片机项目之基于Modbus协议的通讯程序        

  5. ** 备注:晶振11.0592M
  6. ** 功能描述:0X1-0X8与LED0-LED7对应,LED分别代表屏相应的位的状态,对应输出为P1口
  7.              6X1-6X8最后写入对应的值可以在数码管上显示,例如:6X1写入100数码管显示100,
  8.              往6X3里面写入200数码管显示200 ,数码管显示最后一次修改的寄存器的值。                                                                                          
  9. ** 作 者:   吴鉴鹰
  10. ** 日 期:   15.03.26
  11. **作者所属单位:鉴鹰电子工作室
  12. **交流QQ群: 第一群:  198387118  第二群:239316959
  13. ** 微信公众号:单片机精讲吴鉴鹰
  14. **申明:转载请标明作品来源 知识产权归作者吴鉴鹰所有!

  15. 备注:有什么错误的地方,欢迎各大读者指正

  16. O(∩_∩)O~
  17. *******************************************************/

  18. #include<reg52.h>                          // 包含52单片机头文件,此头文件中包含52单片机中的资源定义,包括IO口,寄存器等
  19. #include<intrins.h>                                          //nop延时头文件,在延时函数中用到,调用一个_nop_()代表延时1us。

  20. /* 宏定义无符号字符型、整形、长整形 */
  21. #define uchar unsigned char                            //8位
  22. #define ulint unsigned long                            //32位
  23. #define uint unsigned int                            //16位

  24. uchar idata Send_buf[30];                            //发送数据数组
  25. uchar idata Receive_buf[30];                    //接收数据数组
  26. uint  idata disp[8]={0,0,0,0,0,0,0,0};  //字接收显示数组,用于存储6x1-6x8的十六位接收数据
  27. uchar Data_Count=0,time=0;                                //count为收到数据的次数,time应用于发送03代码时,中间的字数量是多少个数值
  28. uchar Receive_Finish_Flag=0,flag_led=0;        //是否接收完成位,flag_led暂时不用
  29. uint  address_num=0;                                    //接收到字的数值
  30. uint  begin_address=0,address_leg=0;    //数值字开始位,数值字长度
  31. uchar Pd_Flag_7,Pd_Flag_6,Pd_Flag_5,Pd_Flag_4,Pd_Flag_3,Pd_Flag_2,Pd_Flag_1,Pd_Flag_0;//用于判定发送的8个位,即0x1-0x8的位状态

  32. //* LED亮灭情况表示相应的位状态,LED0-LED7分别对于0x1-0x8*//
  33. sbit LED_OUT_0=P1^0;                                                  
  34. sbit LED_OUT_1=P1^1;
  35. sbit LED_OUT_2=P1^2;
  36. sbit LED_OUT_3=P1^3;
  37. sbit LED_OUT_4=P1^4;
  38. sbit LED_OUT_5=P1^5;
  39. sbit LED_OUT_6=P1^6;
  40. sbit LED_OUT_7=P1^7;
  41. sbit KEY_OUT_3=P3^2;
  42. sbit KEY_OUT_4=P3^3;


  43. /**************************数码管显示相关,DuanMa是显示0-9*****************************/
  44. uchar code DuanMa[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};// 显示段码值0~9

  45. /*****16位CRC检验表,低位在前,高位在后*******/

  46. /*********CRC校验 高位表************/
  47. uchar code auchCRCHi[] = {
  48. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
  49. 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
  50. 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
  51. 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
  52. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,
  53. 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
  54. 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
  55. 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
  56. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
  57. 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
  58. 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
  59. 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  60. 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
  61. 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
  62. 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
  63. 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  64. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
  65. 0x40
  66. } ;

  67. /*********CRC校验 低位表************/
  68. uchar code auchCRCLo[] = {
  69. 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4,
  70. 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
  71. 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD,
  72. 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
  73. 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7,
  74. 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
  75. 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE,
  76. 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
  77. 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2,
  78. 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
  79. 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB,
  80. 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
  81. 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91,
  82. 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
  83. 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88,
  84. 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
  85. 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80,
  86. 0x40
  87. } ;


  88. /*****************************************************************************
  89. ** 函数名称: uint crc16(uchar *puchMsg,uchar usDataLen)         
  90. ** 功能描述:  16位CRC校验函数,查表法*
  91. ** 输 入:    uchar *puchMsg,uchar usDataLen
  92. **            校验的数组首地址  校验的数据个数   
  93. **        
  94. ** 输 出:
  95. **         
  96. ** 全局变量:
  97. ** 调用模块:
  98. **
  99. ** 作 者:    吴鉴鹰
  100. ** 日 期:     14.03.26
  101. ******************************************************************************/
  102. uint crc16(uchar *puchMsg,uchar usDataLen)         
  103. {                                                                                         
  104.         uchar uchCRCHi = 0xFF ;                                 
  105.         uchar uchCRCLo = 0xFF ;                                 
  106.         uint uIndex ;                                                         
  107.         while (usDataLen--)                                         
  108.         {
  109.                 uIndex = uchCRCHi ^ *puchMsg++ ;         
  110.                 uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ;
  111.                 uchCRCLo = auchCRCLo[uIndex] ;
  112.         }
  113.         return (((uint)(uchCRCLo) << 8) | uchCRCHi) ;
  114. }

  115. /*****************************************************************************
  116. ** 函数名称:  void delay_us(int n)        
  117. ** 功能描述:  延时子程序,延迟N us
  118. ** 输 入:    int n 延时的时间
  119. **            
  120. **        
  121. ** 输 出:
  122. **         
  123. ** 全局变量:
  124. ** 调用模块:
  125. **
  126. ** 作 者:    吴鉴鹰
  127. ** 日 期:     15.03.26
  128. ******************************************************************************/
  129. /********延时子程序,延迟N us*************/
  130. void delay_us(int n)
  131. {
  132.         int i;
  133.         for(i=n;n>0;n--)
  134.         _nop_();
  135. }

  136. /*****************************************************************************
  137. ** 函数名称:  void delay_ms(int n)
  138. ** 功能描述:  延时子程序,延迟N ms
  139. ** 输 入:    int n 延时的时间
  140. **            
  141. **        
  142. ** 输 出:
  143. **         
  144. ** 全局变量:
  145. ** 调用模块:
  146. **
  147. ** 作 者:    吴鉴鹰
  148. ** 日 期:     15.03.26
  149. ******************************************************************************/
  150. void delay_ms(int n)
  151. {
  152.         int i,j;
  153.         for(i=n;i>0;i--)
  154.                 for(j=141;j>0;j--);
  155. }

  156. /*****************************************************************************
  157. ** 函数名称:  void Led_Display_Fuc(uint Num)  
  158. ** 功能描述:  数码管显示函数,最多显示五位数,数值仅限于0-9,
  159.               该函数根据实际情况选择使用
  160. ** 输 入:    uint Num  要显示的数字
  161. **            
  162. **        
  163. ** 输 出:
  164. **         
  165. ** 全局变量:
  166. ** 调用模块:
  167. **
  168. ** 作 者:    吴鉴鹰
  169. ** 日 期:     15.03.26
  170. ******************************************************************************/
  171. void Led_Display_Fuc(uint Num)           
  172. {
  173.         uint i;
  174.         for (i=0;i<5; i++)
  175.         {
  176.                 P2 = 0;                       //清除显示,防止数字重影
  177.                 P0 = DuanMa[Num%10];           //显示最低一位数
  178.                 delay_us(10);
  179.                 P2 = 0x80>>i;                         //显示第一位数时点亮第一个数码管,第二位时点亮第二个数码管,以此类推。
  180.                 Num = Num/10;                         //将变量除以10处理将显示下一位数        
  181.                    delay_ms(1);
  182.         }
  183. }



 楼主| 吴鉴鹰 发表于 2015-4-14 16:44 | 显示全部楼层
第五讲:基于单片机的Modbus通讯程序设计(二)


  1. /*****************************************************************************
  2. ** 函数名称: void init_uart(void)
  3. ** 功能描述: 串口初始化函数
  4. ** 输 入: int n 延时的时间
  5. **
  6. **
  7. ** 输 出:
  8. **
  9. ** 全局变量:
  10. ** 调用模块:
  11. ** 备注:设定的参数为9600,N,8,1
  12. 串口模式为2,即8位数据位,停止位为1,无校验
  13. ** 作 者: 吴鉴鹰
  14. ** 日 期: 15.03.26
  15. ******************************************************************************/
  16. void init_uart(void)
  17. {
  18. TH1 = 0xfa;
  19. TL1 = 0xfa; // 波特率设为9600
  20. TMOD = 0x21; // 使用T1定时器,模式2
  21. PCON = PCON | 0x80; // 启用波特率加强位
  22. SCON = 0x50; // 串口模式为2,即8位数据位,停止位为1,无校验
  23. PS = 1; // 设定串口中断优先级为最高
  24. TR1 = 1; // 开始定时
  25. ES = 1;         // 打开串口中断
  26. EA = 1; // 打开总中断
  27. }

  28. /*****************************************************************************
  29. ** 函数名称: void Send_Data_Fuc(uchar num)
  30. ** 功能描述: 发送函数
  31. 发送一个字符即一个字节
  32. ** 输 入: uchar num 发送的数据或者字符
  33. **
  34. **
  35. ** 输 出:
  36. **
  37. ** 全局变量:
  38. ** 调用模块:
  39. ** 备注:设定的参数为9600,N,8,1
  40. 串口模式为2,即8位数据位,停止位为1,无校验
  41. ** 作 者: 吴鉴鹰
  42. ** 日 期: 15.03.26
  43. ******************************************************************************/
  44. void Send_Data_Fuc(uchar num)
  45. {
  46. SBUF=num;         //把字符放到发送数据缓存区SBUF,num可以是字符也可以是一个字节数据
  47. while(!TI);         //当发送完之后,TI自动置位,即TI=1,表示发送完成
  48. TI = 0;         //当发送完之后TI不会自动置0,所以需手动将其置0,表示还没发送完数据
  49. }


  50. /*****************************************************************************
  51. ** 函数名称: void send_word(uchar *mydata,uchar num)
  52. ** 功能描述: 发送函数
  53. 发送字符串或者一连串的字节数据
  54. ** 输 入: uchar *mydata,uchar num
  55. ** mydata表示要发送的字符串数组,num表示数组长度
  56. **
  57. ** 输 出:
  58. **
  59. ** 全局变量:
  60. ** 调用模块:
  61. ** 备注:设定的参数为9600,N,8,1
  62. 串口模式为2,即8位数据位,停止位为1,无校验
  63. ** 作 者: 吴鉴鹰
  64. ** 日 期: 15.03.26
  65. ******************************************************************************/
  66. void send_word(uchar *mydata,uchar num)
  67. {
  68. int i;
  69. for(i=0;i<num;i++)
  70. {
  71. Send_Data_Fuc(*(mydata+i));
  72. }
  73. Data_Count = 0;
  74. }

  75. /*****************************************************************************
  76. ** 函数名称: void Com_Data_Receive() interrupt 4 using 1
  77. ** 功能描述: 中断接收函数
  78. 当数据接收完时,进入串口中断将接收的值放入数组
  79. ** 输 入:
  80. **
  81. ** 输 出:
  82. **
  83. ** 全局变量:
  84. ** 调用模块:
  85. ** 作 者: 吴鉴鹰
  86. ** 日 期: 15.03.26
  87. ******************************************************************************/
  88. void Com_Data_Receive() interrupt 4 using 1
  89. {
  90. if(RI)         //当接收完一个字节的数据后,RI会自动置位,即RI=1
  91. {
  92. uchar a;
  93. RI=0;         //接受中断标志软件清零
  94. a=SBUF;         //把缓存在单片机的数据给a
  95. Receive_buf[Data_Count]=a;        //将接受数据放入预置数组
  96. Data_Count++;         //数组自动递增,用于存储下一个数据
  97. if(Data_Count == 8)         //当接收完8个MODBUS的功能码之后,自动清0,从新接收(支持的01、05、03、06命令读取或者写入每次都发送8个字节)
  98. {
  99. Data_Count = 0;
  100. Receive_Finish_Flag = 1;         //接受完8个MODBUS功能码的标志位
  101. }
  102. }
  103. }

  104. /*****************************************************************************
  105. ** 函数名称: void Com_Data_Mng(void)
  106. ** 功能描述: MODBUS功能码处理
  107. 能识别01,03,05,06功能码,可以实现一对多通讯
  108. ** 输 入:
  109. **
  110. ** 输 出:
  111. **
  112. ** 全局变量:
  113. ** 调用模块:
  114. ** 作 者: 吴鉴鹰
  115. ** 日 期: 15.03.26
  116. ******************************************************************************/
  117. void Com_Data_Mng(void)
  118. {
  119. //uint begin_address=0,address_leg=0,crc_end;
  120. uint crc_end,legg;         //CEC校验值和03功能码发送的位的长度
  121. char hi_type,low_type;         //03、06功能码发送字节高低位
  122. if(Receive_buf[0]== 0xa1) //判断机器号码
  123. {
  124. if(Receive_buf[1] == 0x01)         //01功能码
  125. {
  126. //begin_address=Receive_buf[2]<<8+Receive_buf[3];
  127. //address_leg=Receive_buf[4]<<8+Receive_buf[5];
  128. crc_end = crc16(Receive_buf,6);         //校验
  129. if(crc_end == Receive_buf[6]<<8 | Receive_buf[7])//当校验通过时时
  130. {
  131. hi_type=0;         //高位状态
  132. low_type=Pd_Flag_0 | Pd_Flag_1 | Pd_Flag_2 | Pd_Flag_3 | Pd_Flag_4 | Pd_Flag_5 | Pd_Flag_6 | Pd_Flag_7;         //低位状态
  133. //low_type=~P0;
  134. Send_buf[0] = Receive_buf[0];         //站号
  135. Send_buf[1] = Receive_buf[1];         //功能码
  136. Send_buf[2] = 0x02;         //字节数
  137. Send_buf[3] = low_type;         //低位状态,即LED开关情况
  138. Send_buf[4] = hi_type;         //高位状态
  139. crc_end = crc16(Send_buf,5);         //校验
  140. Send_buf[5] = crc_end%256;         //校验低位
  141. Send_buf[6] = crc_end>>8;         //校验高位
  142. send_word(Send_buf,7);         //发送返回屏
  143. }
  144. }
  145. if(Receive_buf[1] == 0x05)         //05功能码
  146. {
  147. begin_address=Receive_buf[3];         //开始地址
  148. crc_end=crc16(Receive_buf,6);         //校验
  149. if(crc_end==Receive_buf[6]<<8|Receive_buf[7])         //校验正确时
  150. {
  151. if(Receive_buf[4]==0xff)         //当为强制打开时
  152. {
  153. switch(begin_address)         //对应的地址
  154. {
  155. case 0x00: LED_OUT_0 = 0; Pd_Flag_0 = 0x01; break;        //相应的LED点亮,记录下相应的P0位状态
  156. case 0x01: LED_OUT_1 = 0; Pd_Flag_1 = 0x02; break;
  157. case 0x02: LED_OUT_2 = 0; Pd_Flag_2 = 0x04; break;
  158. case 0x03: LED_OUT_3 = 0; Pd_Flag_3 = 0x08; break;
  159. case 0x04: LED_OUT_4 = 0; Pd_Flag_4 = 0x10; break;
  160. case 0x05: LED_OUT_5 = 0; Pd_Flag_5 = 0x20; break;
  161. case 0x06: LED_OUT_6 = 0; Pd_Flag_6 = 0x40; break;
  162. case 0x07: LED_OUT_7 = 0; Pd_Flag_7 = 0x80; break;
  163. }        
  164. }
  165. else         //当强制为OFF时
  166. {
  167. //flag_led=0;
  168. switch(begin_address)
  169. {
  170. case 0x00: LED_OUT_0=1; Pd_Flag_0=0; break;         //相应的LED熄灭,记录下相应的P0位状态
  171. case 0x01: LED_OUT_1=1; Pd_Flag_1=0; break;
  172. case 0x02: LED_OUT_2=1; Pd_Flag_2=0; break;
  173. case 0x03: LED_OUT_3=1; Pd_Flag_3=0; break;
  174. case 0x04: LED_OUT_4=1; Pd_Flag_4=0; break;
  175. case 0x05: LED_OUT_5=1; Pd_Flag_5=0; break;
  176. case 0x06: LED_OUT_6=1; Pd_Flag_6=0; break;
  177. case 0x07: LED_OUT_7=1; Pd_Flag_7=0; break;
  178. }
  179. }        
  180. Send_buf[0]=Receive_buf[0];         //站号
  181. Send_buf[1]=Receive_buf[1];         //功能码
  182. Send_buf[2]=Receive_buf[2];         //起始高位
  183. Send_buf[3]=Receive_buf[3];         //起始低位
  184. Send_buf[4]=Receive_buf[4];         //返回状态
  185. Send_buf[5]=Receive_buf[5];         //返回状态
  186. crc_end=crc16(Send_buf,6);         //校验
  187. Send_buf[6]=crc_end%256;         //校验低位
  188. Send_buf[7]=crc_end>>8;         //校验高位
  189. send_word(Send_buf,8);         //发送返回屏
  190. }
  191. }        
  192. if(Receive_buf[1]==0x03)         //03功能码
  193. {
  194. crc_end=crc16(Receive_buf,6);         //校验
  195. if(crc_end == Receive_buf[6]<<8|Receive_buf[7])        //校验一致
  196. {
  197. begin_address=Receive_buf[2]<<8|Receive_buf[3];
  198. address_leg=Receive_buf[4]<<8 | Receive_buf[5];         //总寄存器长度
  199. hi_type=0;
  200. Send_buf[0]=Receive_buf[0];         //站号
  201. Send_buf[1]=Receive_buf[1];         //功能码
  202. legg=(uint)address_leg*2;         //字节数
  203. Send_buf[2]=address_leg*2;;         //字节数
  204. for(time=0;time<legg;time++)         //发送相应字节
  205. {
  206. if(!(time%2))         //字高位为0
  207. Send_buf[time+3] = disp[time/2+begin_address]/256;         //字高字节
  208. else
  209. Send_buf[time+3] = disp[time/2+begin_address]%256;         //字低字节
  210. }
  211. crc_end=crc16(Send_buf,legg+3);         //校验
  212. Send_buf[legg+3]=crc_end%256;         //校验低位
  213. Send_buf[legg+4]=crc_end>>8;         //校验高位
  214. send_word(Send_buf,legg+5);         //返回屏
  215. }
  216. }
  217. if(Receive_buf[1]==0x06)         //06功能码
  218. {
  219. begin_address=Receive_buf[2]<<8|Receive_buf[3]; //写入地址
  220. address_num=Receive_buf[4]<<8|Receive_buf[5];        //寄存器值
  221. crc_end=crc16(Receive_buf,6);         //校验
  222. if(crc_end==Receive_buf[6]<<8|Receive_buf[7])        //校验正确
  223. {
  224. disp[begin_address]=address_num;         //存入数组,给03功能码调用数值
  225. Send_buf[0]=Receive_buf[0];         //站号
  226. Send_buf[1]=Receive_buf[1];         //功能码
  227. Send_buf[2]=Receive_buf[2];         //开始高位
  228. Send_buf[3]=Receive_buf[3];         //开始低位
  229. Send_buf[4]=Receive_buf[4];         //字高位
  230. Send_buf[5]=Receive_buf[5];         //字低位
  231. crc_end=crc16(Send_buf,6);         //校验
  232. Send_buf[6]=crc_end%256;         //校验低位
  233. Send_buf[7]=crc_end>>8;         //校验高位
  234. send_word(Send_buf,8);         //返回屏

  235. }
  236. }
  237. }
  238. }

  239. /*****************************************************************************
  240. ** 函数名称: void main(void)
  241. ** 功能描述: 主函数

  242. ** 输 入:
  243. **
  244. **
  245. ** 输 出:
  246. **
  247. ** 全局变量:
  248. ** 调用模块:
  249. ** 作 者: 吴鉴鹰
  250. ** 日 期: 15.03.26
  251. ******************************************************************************/
  252. void main(void)
  253. {
  254. init_uart();         //初始化串口
  255. while(1)
  256. {
  257. Led_Display_Fuc(address_num);         //在开发板数码管上显示相应位的数值,发送或者接受数据会暂停显示(数码管闪烁)
  258. //按钮输入
  259. if(!KEY_OUT_3) //判断按钮是否按下
  260. {
  261. delay_ms(2);         //延时
  262. while (!KEY_OUT_3);
  263. //delay_ms(2);
  264. LED_OUT_2=!LED_OUT_2;
  265. if(LED_OUT_2)
  266. {
  267. Pd_Flag_2=0x0;
  268. }
  269. else
  270. {
  271. Pd_Flag_2=0x4;
  272. }        
  273. }
  274. if(!KEY_OUT_4)
  275. {
  276. delay_ms(2);
  277. while (!KEY_OUT_4);
  278. //delay_ms(2);
  279. LED_OUT_3=!LED_OUT_3;
  280. if(LED_OUT_3)
  281. {
  282. Pd_Flag_3=0x0;
  283. }
  284. else
  285. {
  286. Pd_Flag_3=0x8;
  287. }
  288. }
  289. while(Receive_Finish_Flag)         //当接收完成时
  290. {
  291. Com_Data_Mng();         //识别相应的功能码
  292. Receive_Finish_Flag=0;         //重新接收        
  293. }        
  294. }        
  295. }


xiamisz 发表于 2015-4-15 14:33 | 显示全部楼层
帖子真的很有用,学习了
solarddd 发表于 2015-4-15 15:34 | 显示全部楼层
学习了!!
nkzou 发表于 2015-4-15 16:38 | 显示全部楼层
谢谢分享,先收藏了!
supaopcb 发表于 2015-4-15 17:06 | 显示全部楼层
 楼主| 吴鉴鹰 发表于 2015-4-16 10:06 | 显示全部楼层
xiamisz 发表于 2015-4-15 14:33
帖子真的很有用,学习了

谢谢鼓励,我会一直分享下去的。
 楼主| 吴鉴鹰 发表于 2015-4-17 08:48 | 显示全部楼层
supaopcb 发表于 2015-4-17 15:39 | 显示全部楼层
有客户介绍下  谢谢
 楼主| 吴鉴鹰 发表于 2015-4-18 22:46 | 显示全部楼层
xiamisz 发表于 2015-4-15 14:33
帖子真的很有用,学习了

谢谢鼓励和支持,有一点点帮助我就心满意足了。
longxingshi 发表于 2015-4-19 17:01 | 显示全部楼层
言之有理
 楼主| 吴鉴鹰 发表于 2015-4-19 20:10 | 显示全部楼层
supaopcb 发表于 2015-4-17 15:39
有客户介绍下  谢谢

大家共同进步,多多交流
 楼主| 吴鉴鹰 发表于 2015-4-19 20:11 | 显示全部楼层

多多交流,互相探讨技术难题:handshake
Dongfangyuxiao 发表于 2015-4-19 22:57 | 显示全部楼层
高质量C++/C编程指南
文件标识:
当前版本:1.0
作    者:林锐 博士
文件状态  [  ] 草稿文件 [√] 正式文件 [  ] 更改正式文件  
完成日期: 2001年7月24日
 楼主| 吴鉴鹰 发表于 2015-4-20 10:32 | 显示全部楼层
Dongfangyuxiao 发表于 2015-4-19 22:57
高质量C++/C编程指南
文件标识:
当前版本:1.0

这个格式蛮好的,你可以为大家分享一下。
 楼主| 吴鉴鹰 发表于 2015-4-21 17:44 | 显示全部楼层

这个话有歧义:1、让我等着,让我好看  2、等着我的分享:lol
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 在线客服 返回列表 返回顶部