找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6299|回复: 10
收起左侧

支持作为Modbus从站设备的Modbus RTU模式的源码

  [复制链接]
ID:360570 发表于 2018-6-27 20:47 | 显示全部楼层 |阅读模式
  1. //----------------------------------------------------------------------------//
  2. //此代码只支持作为Modbus从站设备的Modbus RTU模式
  3. //
  4. //支持的功能码:
  5. //0x03 读保持寄存器(读多个保持寄存器的值,有效地位为0-99)
  6. //0x06 写单个寄存器(写入一个寄存器的值,有效地址为0-99)
  7. //0x10 写多个寄存器(写入多个寄存器的值,有效地址为0-99)
  8. //
  9. //支持的异常码:
  10. //0x01 非法功能码(不支持的功能码)
  11. //0x02 非法数据地址(起始地址不在有效范围内)
  12. //0x03 非法数据值(在起始地址的基础上,数量是不合法的)
  13. //----------------------------------------------------------------------------//

  14. #include "Modbus.h"
  15. #include "main.h"

  16. /* 变量定义 ------------------------------------------------------------------*/
  17. uint8_t Modbus_Send_Buff[Modbus_Max_Send_Buff];                //发送数据缓冲区
  18. uint8_t Modbus_Rcv_Buff[Modbus_Max_Rcv_Buff];                //接收数据缓冲区
  19. uint8_t Modbus_Timeout_Cnt;                                                        //定时器中断计数
  20. uint8_t Modbus_Rcv_Cnt;                                                                //接收字节计数
  21. uint8_t        Modbus_Rcv_flag;                                                        //设备进入接收状态标志
  22. uint8_t Modbus_Cmd_flag;                                                        //设备进入命令解析状态标志
  23. uint8_t Modbus_Exe_flag;                                                        //设备进入命令执行状态标志
  24. uint8_t Modbus_Function;                                                        //从站设备需执行的功能

  25. uint16_t HoldingReg[100] = {0x0123, 0x4567, 0x89AB, 0xCDEF};                                //保持寄存器

  26. /* 函数定义 ------------------------------------------------------------------*/

  27. //----------------------------------------------------------------------------//
  28. //函数功能:逐位计算法CRC16校验,在Modbus中CRC结果要进行高低字节交换,即低字节在前,高字节在后
  29. //入口参数:puchMsg是要进行CRC校验的消息;usDataLen是消息中字节数
  30. //出口参数:计算出来的CRC校验码,16位长度
  31. //最后修改:2015.11.29
  32. //备注:
  33. //----------------------------------------------------------------------------//
  34. uint16_t Modbus_CRC16(uint8_t *puchMsg, uint8_t usDataLen)
  35. {
  36.         uint16_t CRC_Cal = 0xFFFF;
  37.         uint8_t CRC_High, CRC_Low;
  38.         uint8_t i, j;
  39.         
  40.         for(j = 0; j < usDataLen; j++)
  41.         {
  42.                 CRC_Cal = CRC_Cal ^ *puchMsg++;
  43.                
  44.                 for (i = 0; i < 8; i++)
  45.                 {
  46.                         if((CRC_Cal & 0x0001) == 0x0001)
  47.                         {
  48.                                 CRC_Cal = CRC_Cal >> 1;
  49.                                 CRC_Cal = CRC_Cal ^ 0xA001;
  50.                         }
  51.                         else
  52.                         {
  53.                                 CRC_Cal = CRC_Cal >> 1;
  54.                         }
  55.                 }
  56.         }
  57.         
  58.         CRC_High = (uint8_t)(CRC_Cal >> 8);
  59.         CRC_Low = (uint8_t)(CRC_Cal & 0x00FF);
  60.         
  61.         return (CRC_Low << 8 | CRC_High);
  62.         
  63. //        return CRC_Cal;

  64. }

  65. //----------------------------------------------------------------------------//
  66. //函数功能:Modbus初始化
  67. //入口参数:ID是从站站号
  68. //出口参数:无
  69. //最后修改:2015.11.20
  70. //备注:
  71. //----------------------------------------------------------------------------//
  72. void Modbus_Init(void)
  73. {
  74.         uint16_t i;
  75.         
  76.         //----------------------------------------------------------//
  77.         //Modbus相关变量初始化
  78.         //----------------------------------------------------------//
  79.         Modbus_Timeout_Cnt = 0;
  80.         Modbus_Rcv_Cnt = 0;
  81.         Modbus_Rcv_flag = 0;
  82.         Modbus_Cmd_flag = 0;
  83.         Modbus_Exe_flag = 0;
  84.         
  85.         for(i = 0; i < Modbus_Max_Rcv_Buff; i++)                //清除接收缓冲区
  86.         {
  87.                 Modbus_Rcv_Buff[i] = '\0';
  88.         }
  89.         
  90.         for(i = 0; i < Modbus_Max_Send_Buff; i++)                //清除发送缓冲区
  91.         {
  92.                 Modbus_Send_Buff[i] = '\0';
  93.         }
  94.         
  95.         //----------------------------------------------------------//
  96.         //TIM2定时器使能
  97.         //----------------------------------------------------------//
  98.         TIM_Cmd(TIM2, ENABLE);
  99. }

  100. //----------------------------------------------------------------------------//
  101. //函数功能:Modbus命令解析函数
  102. //入口参数:无
  103. //出口参数:无
  104. //最后修改:2015.12.11
  105. //备注:
  106. //----------------------------------------------------------------------------//
  107. void Modbus_Cmd(void)
  108. {
  109.         uint8_t Modbus_CRC_Rcv_Hi;                //接收到的ModbusCRC校验码高字节
  110.         uint8_t Modbus_CRC_Rcv_Lo;                //接收到的ModbusCRC校验码低字节
  111.         uint16_t Modbus_CRC_Rcv;                //接收到的ModbusCRC校验码
  112.         uint16_t Modbus_CRC_Cal;                //根据接收到的数据计算出来的CRC值
  113.         
  114.         //----------------------------------------------------------//
  115.         //开始命令解析
  116.         //----------------------------------------------------------//
  117.         if(Modbus_Cmd_flag == 1)
  118.         {
  119.                 if(Modbus_Rcv_Cnt > 4)                //如果接收到的一帧的字节数大于4 首先确保帧的长度在正常范围
  120.                 {
  121.                         Modbus_CRC_Rcv_Lo = Modbus_Rcv_Buff[Modbus_Rcv_Cnt - 2];                                        //接收到的ModbusCRC校验码低字节
  122.                         Modbus_CRC_Rcv_Hi = Modbus_Rcv_Buff[Modbus_Rcv_Cnt - 1];                                        //接收到的ModbusCRC校验码高字节
  123.                         Modbus_CRC_Rcv = (uint16_t)(Modbus_CRC_Rcv_Lo << 8 | Modbus_CRC_Rcv_Hi);        //接收到的ModbusCRC校验码(16位)
  124.                         Modbus_CRC_Cal = Modbus_CRC16(Modbus_Rcv_Buff, Modbus_Rcv_Cnt - 2);                        //根据接收到的数据计算CRC值
  125.                         
  126.                         if(Modbus_CRC_Cal == Modbus_CRC_Rcv)                //如果计算的CRC值与接受的CRC值相等
  127.                         {
  128.                                 //USART_SendByte(USART1, 0xAC);
  129.                                 if(Slave_Address == Modbus_Rcv_Buff[0])        //如果是本机地址
  130.                                 {
  131.                                         switch(Modbus_Rcv_Buff[1])                        //用switch分支语句来确定功能
  132.                                         {
  133.                                         case Modbus_ReadHoldingReg:                                                //如果是读保存寄存器
  134.                                                 Modbus_Function = Modbus_ReadHoldingReg;        //将从站设备需执行的功能赋值为读保存寄存器
  135.                                                 Modbus_Exe_flag = 1;                                                //设备进入命令执行状态
  136.                                                 break;                                                                                //跳出分支语句
  137.                                                 
  138.                                         case Modbus_WriteSingleReg:
  139.                                                 Modbus_Function = Modbus_WriteSingleReg;        //将从站设备需执行的功能赋值为写单个寄存器
  140.                                                 Modbus_Exe_flag = 1;                                                //设备进入命令执行状态
  141.                                                 break;                                                                                //跳出分支语句
  142.                                        
  143.                                         case Modbus_WriteMultipleReg:
  144.                                                 Modbus_Function = Modbus_WriteMultipleReg;        //将从站设备需执行的功能赋值为写多个寄存器
  145.                                                 Modbus_Exe_flag = 1;                                                //设备进入命令执行状态
  146.                                                 break;                                                                                //跳出分支语句
  147.                                                 
  148.                                         default:
  149.                                                 Modbus_ErrorHandling(0x01);                //所有功能码都不符合,则返回功能码错误异常响应报文
  150.                                                 return;
  151.                                         }
  152.                                 }
  153.                                 
  154.                                 else                //否则清空接收数据缓冲区和发送数据缓冲区
  155.                                 {
  156.                                         Modbus_ClearBuff();
  157.                                 }
  158.                         }
  159.                         
  160.                         else                //否则清空接收数据缓冲区和发送数据缓冲区
  161.                         {
  162.                                 Modbus_ClearBuff();
  163.                         }
  164.                         
  165.                 }
  166.                
  167.                 else                //否则清空接收数据缓冲区和发送数据缓冲区
  168.                 {
  169.                         Modbus_ClearBuff();
  170.                 }
  171.                
  172.                 Modbus_Cmd_flag = 0;                //设备退出命令解析状态标志
  173.         }
  174. }

  175. //----------------------------------------------------------------------------//
  176. //函数功能:Modbus命令执行函数
  177. //入口参数:无
  178. //出口参数:无
  179. //最后修改:2015.12.6
  180. //备注:
  181. //----------------------------------------------------------------------------//
  182. void Modbus_Exe(void)
  183. {
  184.         if(Modbus_Exe_flag == 1)
  185.         {
  186.                 switch(Modbus_Function)
  187.                 {
  188.                 case Modbus_ReadHoldingReg:
  189.                         Modbus_ReadHoldingReg_Process();
  190.                         break;
  191.                         
  192.                 case Modbus_WriteSingleReg:
  193.                         Modbus_WriteSingleReg_Process();
  194.                         break;
  195.                
  196.                 case Modbus_WriteMultipleReg:
  197.                         Modbus_WriteMultipleReg_Process();
  198.                         break;
  199.                         
  200.                 }
  201.                 Modbus_Exe_flag = 0;
  202.         }
  203. }

  204. //----------------------------------------------------------------------------//
  205. //函数功能:功能码0x03,读保持寄存器
  206. //入口参数:无
  207. //出口参数:无
  208. //最后修改:2015.12.5
  209. //备注:
  210. //----------------------------------------------------------------------------//
  211. void Modbus_ReadHoldingReg_Process(void)
  212. {
  213.         uint8_t Send_Cnt;                        //发送字节数量
  214.         uint16_t StartAddress_Reg;        //要读取的寄存器起始地址
  215.         uint16_t Num_Reg;                        //要读取的寄存器的数量
  216.         uint16_t CRC_Cal;                        //CRC校验码
  217.         uint16_t i, j;                                //临时变量
  218.         
  219.         StartAddress_Reg = Modbus_Rcv_Buff[2] << 8 | Modbus_Rcv_Buff[3];        //从接收数据缓冲区得到要读取的寄存器起始地址
  220.         Num_Reg = Modbus_Rcv_Buff[4] << 8 | Modbus_Rcv_Buff[5];                                //从接收数据缓冲区得到要读取的寄存器数量
  221.         
  222.         if(StartAddress_Reg < 100)                //寄存器起始地址在正确范围内
  223.         {
  224.                 if(StartAddress_Reg + Num_Reg < 100 && Num_Reg > 0)                //起始地址+寄存器数量位于正确范围内 并且 寄存器数量正确
  225.                 {        
  226.                         Send_Cnt = 3 + (Num_Reg << 1) + 2;                //计算发送字节数量
  227.         
  228.                         Modbus_Send_Buff[0] = Slave_Address;                        //从站地址
  229.                         Modbus_Send_Buff[1] = Modbus_ReadHoldingReg;        //功能码
  230.                         Modbus_Send_Buff[2] = Num_Reg << 1;                                //寄存器字节数量 等于 寄存器数量乘2
  231.                         
  232.                         for(i = StartAddress_Reg, j = 3; i < StartAddress_Reg + Num_Reg; i++, j += 2)        //读取寄存器的数据
  233.                         {
  234.                                 Modbus_Send_Buff[j] = (uint8_t)(HoldingReg[i] >> 8);
  235.                                 Modbus_Send_Buff[j + 1] = (uint8_t)(HoldingReg[i] & 0x00FF);
  236.                         }
  237.         
  238.                         CRC_Cal = Modbus_CRC16(Modbus_Send_Buff, 3 + (Num_Reg << 1));                                //计算发送数据的CRC校验码
  239.                         Modbus_Send_Buff[3 + (Num_Reg << 1)] = (uint8_t)(CRC_Cal >> 8);                                //先是低字节
  240.                         Modbus_Send_Buff[3 + (Num_Reg << 1) + 1] = (uint8_t)(CRC_Cal & 0x00FF);                //后是高字节
  241.         
  242.                         USART_SendString(USART1, Modbus_Send_Buff, Send_Cnt);                        //发送响应报文
  243.         
  244.                         Modbus_ClearBuff();                //清空接收数据缓冲区和发送数据缓冲区
  245.                 }
  246.                
  247.                 else
  248.                 {
  249.                         Modbus_ErrorHandling(0x03);                //非法数据值
  250.                 }
  251.         }
  252.         
  253.         else
  254.         {
  255.                 Modbus_ErrorHandling(0x02);                        //非法数据地址
  256.         }
  257.         
  258. }

  259. //----------------------------------------------------------------------------//
  260. //函数功能:功能码0x06,写单个寄存器
  261. //入口参数:无
  262. //出口参数:无
  263. //最后修改:2015.12.6
  264. //备注:
  265. //----------------------------------------------------------------------------//
  266. void Modbus_WriteSingleReg_Process(void)
  267. {
  268.         uint8_t Send_Cnt;                        //发送字节数量
  269.         uint16_t Address_Reg;                //要写入的寄存器地址
  270.         uint16_t Value_Reg;                        //要写入的寄存器值
  271.         uint16_t CRC_Cal;                        //CRC校验码
  272.         
  273.         Address_Reg = Modbus_Rcv_Buff[2] << 8 | Modbus_Rcv_Buff[3];                //从接收数据缓冲区得到要写入的寄存器地址
  274.         Value_Reg = Modbus_Rcv_Buff[4] << 8 | Modbus_Rcv_Buff[5];                //从接收数据缓冲区得到要写入的寄存器值
  275.         
  276.         if(Address_Reg < 100)                //寄存器起始地址在正确范围内
  277.         {
  278.                 Send_Cnt = 6 + 2;                //计算发送字节数量
  279.                
  280.                 HoldingReg[Address_Reg] = Value_Reg;                //将要写入的寄存器值写入寄存器
  281.                
  282.                 Modbus_Send_Buff[0] = Slave_Address;                                                                        //从站地址
  283.                 Modbus_Send_Buff[1] = Modbus_WriteSingleReg;                                                        //功能码
  284.                 Modbus_Send_Buff[2] = (uint8_t)(Address_Reg >> 8);                                                //寄存器地址高字节
  285.                 Modbus_Send_Buff[3] = (uint8_t)(Address_Reg & 0x00FF);                                        //寄存器地址低字节
  286.                 Modbus_Send_Buff[4] = (uint8_t)(HoldingReg[Address_Reg] >> 8);                        //寄存器值高字节
  287.                 Modbus_Send_Buff[5] = (uint8_t)(HoldingReg[Address_Reg] & 0x00FF);                //寄存器值低字节
  288.                
  289.                 CRC_Cal = Modbus_CRC16(Modbus_Send_Buff, 6);                        //计算发送数据的CRC校验码
  290.                 Modbus_Send_Buff[6] = (uint8_t)(CRC_Cal >> 8);                        //先是低字节
  291.                 Modbus_Send_Buff[7] = (uint8_t)(CRC_Cal & 0x00FF);                //后是高字节
  292.                
  293.                 USART_SendString(USART1, Modbus_Send_Buff, Send_Cnt);        //发送响应报文
  294.         
  295.                 Modbus_ClearBuff();                //清空接收数据缓冲区和发送数据缓冲区
  296.         }
  297.         
  298.         else
  299.         {
  300.                 Modbus_ErrorHandling(0x02);                        //非法数据地址
  301.         }
  302. }

  303. //----------------------------------------------------------------------------//
  304. //函数功能:功能码0x10,写多个寄存器
  305. //入口参数:无
  306. //出口参数:无
  307. //最后修改:2015.12.9
  308. //备注:
  309. //----------------------------------------------------------------------------//
  310. void Modbus_WriteMultipleReg_Process(void)
  311. {
  312.         uint8_t Send_Cnt;                        //发送字节数量
  313.         uint16_t StartAddress_Reg;        //要写入的寄存器起始地址
  314.         uint16_t Num_Reg;                        //要写入的寄存器的数量
  315.         uint16_t CRC_Cal;                        //CRC校验码
  316.         uint16_t i, j;                                //临时变量
  317.         
  318.         StartAddress_Reg = Modbus_Rcv_Buff[2] << 8 | Modbus_Rcv_Buff[3];        //从接收数据缓冲区得到要写入的寄存器起始地址
  319.         Num_Reg = Modbus_Rcv_Buff[4] << 8 | Modbus_Rcv_Buff[5];                                //从接收数据缓冲区得到要写入的寄存器数量
  320.         
  321.         if(StartAddress_Reg < 100)                        //寄存器起始地址在正确范围内
  322.         {
  323.                 if(StartAddress_Reg + Num_Reg < 100 && Num_Reg > 0)                                //起始地址+寄存器数量位于正确范围内 并且 寄存器数量正确                        
  324.                 {
  325.                         for(i = StartAddress_Reg, j = 7; i < StartAddress_Reg + Num_Reg; i++, j += 2)        //将要写入的寄存器值写入寄存器
  326.                         {
  327.                                 HoldingReg[i] = Modbus_Rcv_Buff[j] << 8 | Modbus_Rcv_Buff[j + 1];
  328.                         }
  329.                         
  330.                         Send_Cnt = 6 + 2;
  331.                         
  332.                         Modbus_Send_Buff[0] = Slave_Address;                                                //从站地址
  333.                         Modbus_Send_Buff[1] = Modbus_WriteMultipleReg;                                //功能码
  334.                         Modbus_Send_Buff[2] = (uint8_t)(StartAddress_Reg >> 8);                //寄存器起始地址高字节
  335.                         Modbus_Send_Buff[3] = (uint8_t)(StartAddress_Reg & 0x00FF);        //寄存器起始地址低字节
  336.                         Modbus_Send_Buff[4] = (uint8_t)(Num_Reg >> 8);                                //寄存器数量高字节
  337.                         Modbus_Send_Buff[5] = (uint8_t)(Num_Reg & 0x00FF);                        //寄存器数量低字节
  338.                         
  339.                         CRC_Cal = Modbus_CRC16(Modbus_Send_Buff, 6);                        //计算发送数据的CRC校验码
  340.                         Modbus_Send_Buff[6] = (uint8_t)(CRC_Cal >> 8);                        //先是低字节
  341.                         Modbus_Send_Buff[7] = (uint8_t)(CRC_Cal & 0x00FF);                //后是高字节
  342.                         
  343.                         USART_SendString(USART1, Modbus_Send_Buff, Send_Cnt);        //发送响应报文
  344.         
  345.                         Modbus_ClearBuff();                //清空接收数据缓冲区和发送数据缓冲区
  346.                 }
  347.                
  348.                 else
  349.                 {
  350.                         Modbus_ErrorHandling(0x03);
  351.                 }
  352.         }
  353.         
  354.         else
  355.         {
  356.                 Modbus_ErrorHandling(0x02);
  357.         }
  358. }

  359. //----------------------------------------------------------------------------//
  360. //函数功能:错误处理
  361. //入口参数:ErrorType是错误类型
  362. //出口参数:无
  363. //最后修改:2015.12.11
  364. //备注:
  365. //----------------------------------------------------------------------------//
  366. void Modbus_ErrorHandling(uint8_t ErrorType)
  367. {
  368.         uint16_t CRC_Cal;                        //CRC校验码
  369.         
  370.         switch(ErrorType)                        //用switch分支语句来确定Modbus异常码
  371.         {
  372.         case 0x01:                                        //非法功能码
  373.                 Modbus_Send_Buff[0] = Slave_Address;                                        //从站地址
  374.                 Modbus_Send_Buff[1] = Modbus_Rcv_Buff[1] + 0x80;                //异常功能码
  375.                 Modbus_Send_Buff[2] = 0x01;                                                                //异常码
  376.                 CRC_Cal = Modbus_CRC16(Modbus_Send_Buff, 3);                        //计算发送数据的CRC校验码
  377.                 Modbus_Send_Buff[3] = (uint8_t)(CRC_Cal >> 8);                        //先是低字节
  378.                 Modbus_Send_Buff[4] = (uint8_t)(CRC_Cal & 0x00FF);                //后是高字节
  379.                
  380.                 USART_SendString(USART1, Modbus_Send_Buff, 5);                        //发送异常响应报文
  381.                 break;
  382.                
  383.         case 0x02:                                        //非法数据地址
  384.                 Modbus_Send_Buff[0] = Slave_Address;                                        //从站地址
  385.                 Modbus_Send_Buff[1] = Modbus_Rcv_Buff[1] + 0x80;                //异常功能码
  386.                 Modbus_Send_Buff[2] = 0x02;                                                                //异常码
  387.                 CRC_Cal = Modbus_CRC16(Modbus_Send_Buff, 3);                        //计算发送数据的CRC校验码
  388.                 Modbus_Send_Buff[3] = (uint8_t)(CRC_Cal >> 8);                        //先是低字节
  389.                 Modbus_Send_Buff[4] = (uint8_t)(CRC_Cal & 0x00FF);                //后是高字节
  390.                
  391.                 USART_SendString(USART1, Modbus_Send_Buff, 5);                        //发送异常响应报文
  392.                 break;
  393.                
  394.         case 0x03:                                        //非法数据值
  395.                 Modbus_Send_Buff[0] = Slave_Address;                                        //从站地址
  396.                 Modbus_Send_Buff[1] = Modbus_Rcv_Buff[1] + 0x80;                //异常功能码
  397.                 Modbus_Send_Buff[2] = 0x03;                                                                //异常码
  398.                 CRC_Cal = Modbus_CRC16(Modbus_Send_Buff, 3);                        //计算发送数据的CRC校验码
  399.                 Modbus_Send_Buff[3] = (uint8_t)(CRC_Cal >> 8);                        //先是低字节
  400.                 Modbus_Send_Buff[4] = (uint8_t)(CRC_Cal & 0x00FF);                //后是高字节
  401.                
  402.                 USART_SendString(USART1, Modbus_Send_Buff, 5);                        //发送异常响应报文
  403.                 break;
  404.                
  405. //        default:
  406. //                return;
  407.                
  408.         }
  409.         
  410.         Modbus_ClearBuff();                //清空接收数据缓冲区和发送数据缓冲区
  411. }

  412. //----------------------------------------------------------------------------//
  413. //函数功能:清空接收数据缓冲区和发送数据缓冲区
  414. //入口参数:无
  415. //出口参数:无
  416. //最后修改:2015.12.5
  417. //备注:
  418. //----------------------------------------------------------------------------//
  419. void Modbus_ClearBuff(void)
  420. {
  421.         uint16_t i;
  422.         
  423.         for(i = 0; i < Modbus_Max_Rcv_Buff; i++)                //清除接收缓冲区
  424.         {
  425.                 Modbus_Rcv_Buff[i] = '\0';
  426.         }
  427.         Modbus_Rcv_Cnt = 0;                        //接收字节计数清0
  428.         
  429.         for(i = 0; i < Modbus_Max_Send_Buff; i++)                //清除发送缓冲区
  430.         {
  431.                 Modbus_Send_Buff[i] = '\0';
  432.         }
  433.         
  434. }

  435. //----------------------------------------------------------------------------//
  436. //函数功能:把一个字节的高4位十六进制数存到另一个字节的低4位里
  437. //入口参数:一个字节的数据
  438. //出口参数:另一个字节
  439. //最后修改:2015.11.28
  440. //备注:
  441. //----------------------------------------------------------------------------//
  442. uint8_t High4BitsToOneByte(uint8_t Byte)
  443. {
  444.         uint8_t tempByte;
  445.         
  446.         tempByte = (Byte >> 4) & 0x0F;
  447.         
  448.         return tempByte;
  449. }

  450. //----------------------------------------------------------------------------//
  451. //函数功能:把一个字节的低4位十六进制数存到另一个字节的低4位里
  452. //入口参数:一个字节的数据
  453. //出口参数:另一个字节
  454. //最后修改:2015.11.28
  455. //备注:
  456. //----------------------------------------------------------------------------//
  457. uint8_t Low4BitsToOneByte(uint8_t Byte)
  458. {
  459.         uint8_t tempByte;
  460.         
  461.         tempByte = Byte & 0x0F;
  462.         
  463.         return tempByte;
  464. }

  465. //----------------------------------------------------------------------------//
  466. //函数功能:把低4位16进制数转换为在OLED字库上对应的0~9和A~F
  467. //入口参数:HexByte是低4位16进制数
  468. //出口参数:OLED字库上对应的0~9和A~F
  469. //最后修改:2015.11.28
  470. //备注:
  471. //----------------------------------------------------------------------------//
  472. uint8_t HexToOLEDAsc(uint8_t HexByte)
  473. {
  474.         if((HexByte >= 0x00) && (HexByte <= 0x09))                        //数字0~9
  475.         {
  476.                 HexByte += 0x30;
  477.         }
  478.         else if((HexByte >= 0x0A) && (HexByte <= 0x0F))        //数字A~F
  479.         {
  480.                 HexByte += 0x37;
  481.         }
  482.         else
  483.         {
  484.                 HexByte = 0xff;
  485.         }
  486.         
  487.         return HexByte;
  488. }
复制代码
回复

使用道具 举报

ID:20154 发表于 2018-7-7 10:53 | 显示全部楼层
谢谢楼主分享
回复

使用道具 举报

ID:389253 发表于 2018-8-23 13:59 | 显示全部楼层
多谢楼主分享
回复

使用道具 举报

ID:245836 发表于 2018-12-6 14:23 | 显示全部楼层

多谢楼主分享
回复

使用道具 举报

ID:448641 发表于 2019-3-21 22:53 | 显示全部楼层
谢谢楼主分享
回复

使用道具 举报

ID:87734 发表于 2019-4-24 23:33 | 显示全部楼层
楼猪肯定辛苦了,谢谢
回复

使用道具 举报

ID:42131 发表于 2020-1-4 16:13 | 显示全部楼层
学习了   收下代码了
回复

使用道具 举报

ID:699438 发表于 2020-2-28 10:07 | 显示全部楼层
代码很棒,谢谢分享
回复

使用道具 举报

ID:165291 发表于 2022-6-22 10:38 | 显示全部楼层
没有工程下载吗?
回复

使用道具 举报

ID:74687 发表于 2023-5-25 18:47 | 显示全部楼层
楼主有完整代码吗?
回复

使用道具 举报

ID:74687 发表于 2023-5-26 11:38 | 显示全部楼层
感谢楼主,使我理解了清理缓冲区,现在大部分代码跑不了,不少原因就是没有清理缓冲区。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表