|
采用MODBUS协议实现开关量输入输出采集的程序,希望对大家有用,下载使用的时候记得回复哦
本例程是采用 MODBUS 协议实现的,为了实现 MODBUS 协议,我们移植了一个叫FREE MODBUS协议栈。关于 FREE MODBUS协议栈,在这里就不做介绍了,
在阅读例程之前,请大家先学习下标准 MODBUS协议,不然你无法了解功能代码的使用。
接下来我给大家介绍如何在串口调试软件中用MODBUS协议命令点亮从机
板子上的LED灯以及读取板子上按键的状态。
在这个例程的工程文件夹下找一个名为:ECOMV280的文件夹,打开后有一个“ECOM串口助手 V2.80.exe”的软件和好多说明资料,请先阅读下软件的使用方法。等你熟悉了调试软件的使用后,就可以连接板子进行调试了,调试板子前你首先要准备一个 RS485转 RS232的转换器,不然没有办法跟电脑连接。
操作说明:
1、 通讯参数设置:
注意:发送命令的时候一定要按照上图设置,数据按 HEX格式发送,最后还要用CRC校验。
设置完了以后直接在数据输入框中填写发送的命令就行,CRC 校验码用户
不用管,在发送数据时,软件会自动在后面加上的。
3、 接收窗口设置:
注意:终端一定要设置成 HEX显示,否则看不到返回的 代码。
4、 数字量输入采集指令:(采集板子上2个按键的状态)
发送:01 02 00 00 00 02 38 0B 十六进制
备注:如果没有板子按键按下,收到 01 02 01 00 A1 88
板子上按键KEY1按下,收到01 02 01 01 60 48
板子上按键KEY2按下,收到01 02 01 02 20 49
注意:发送时在数据框中只填入红色部分数据,蓝色部分为 CRC校验,软件自动添加。
读取的数据是一个字节,转化为二进制为 8 个位 0000 0000 我们的 3 个
按键的状态对应为:KEY1对应D0位,KEY2对应D1位。
如果按键按下对应的位为 1,如果按键没有按下对应的位为0。
5、 数字量输出控制指令:(控制板子上2个LED灯)
发送:01 0F 00 00 00 02 01 00 8F 57 十六进制
接收:01 0F 00 00 00 02 15 CA 十六进制
写入的一个字节数据转换成二进制为 8个位 0000 0000,LED1对应DO,
LED2对应D1。 “1”表示点亮LED, “0”表示熄灭LED,
例如发送:01 0F 00 00 00 02 01 01 4E 97 表示点亮LED1.
发送:01 0F 00 00 00 02 01 02 0E 96 表示点亮LED2
发送:01 0F 00 00 00 02 01 00 8F 57 表示熄灭所有LED
注意:发送时在数据框中只填入红色部分数据,蓝色部分为CRC校验,软件自动添加
好了,这个例程的应用操作说明就先介绍到这里,祝福大家能操作成功。
stm32单片机源程序如下:
- #include "stm32f10x.h"
- #include "sys.h"
- //#include "usart.h"
- #include "led.h" /*------添加了IO控制端口的头文件------*/
- #include "mb.h"
- #include "mbutils.h"
- //输入寄存器起始地址
- #define REG_INPUT_START 0x0000
- //输入寄存器数量
- #define REG_INPUT_NREGS 8
- //保持寄存器起始地址
- #define REG_HOLDING_START 0x0000
- //保持寄存器数量
- #define REG_HOLDING_NREGS 8
- //线圈起始地址
- #define REG_COILS_START 0x0000
- //线圈数量
- #define REG_COILS_SIZE 16
- //开关寄存器起始地址
- #define REG_DISCRETE_START 0x0000
- //开关寄存器数量
- #define REG_DISCRETE_SIZE 16
- /* Private variables ---------------------------------------------------------*/
- //输入寄存器内容
- uint16_t usRegInputBuf[REG_INPUT_NREGS] = {0x0ed6,0x1001,0x1002,0x1003,0x1004,0x1005,0x1006,0x1007};
- //寄存器起始地址
- uint16_t usRegInputStart = REG_INPUT_START;
- //保持寄存器内容
- uint16_t usRegHoldingBuf[REG_HOLDING_NREGS] = {0x0ed6,0x3f8e,0x147b,0x400e,0x1eb8,0x4055,0x147b,0x408e};
- //保持寄存器起始地址
- uint16_t usRegHoldingStart = REG_HOLDING_START;
- //线圈状态
- uint8_t ucRegCoilsBuf[REG_COILS_SIZE / 8] = {0x03,0x00}; //0x03表示2个LED全亮,这是刚复位后的状态。
- //开关输入状态
- uint8_t ucRegDiscreteBuf[REG_DISCRETE_SIZE / 8] = {0x00,0x00};
- void LED_Poll(void);
- void Button_Poll(void);
- int main(void)
- {
- LED_Config(); //--------LED端口初始化-------------
- Button_Config(); //-----按键端口初始化------------
- eMBInit(MB_RTU, 0x02, 0x01, 9600, MB_PAR_NONE); //初始化 RTU模式 从机地址为1 USART1 9600 无校验
- eMBEnable(); //启动FreeModbus
- while(1)
- {
- eMBPoll();
- LED_Poll();
- Button_Poll();
- }
- }
- void LED_Poll(void)
- {
- uint8_t LED_Status;
- LED_Status = ucRegCoilsBuf[0];
- if(LED_Status & 0x01) {LED1_ON;} else {LED1_OFF;}
- if(LED_Status & 0x02) {LED2_ON;} else {LED2_OFF;}
- //if(LED_Status & 0x04) {LED3_ON;} else {LED3_OFF;}
- }
- void Button_Poll(void)
- {
-
- uint8_t Button_Status = 0x00;
- BUTTON1_READ()?(Button_Status &=~ 0x01):(Button_Status |= 0x01);
- BUTTON2_READ()?(Button_Status &=~ 0x02):(Button_Status |= 0x02);
- //BUTTON3_READ()?(Button_Status &=~ 0x04):(Button_Status |= 0x04);
- ucRegDiscreteBuf[0] = Button_Status;
- }
- /**
- * @brief 输入寄存器处理函数,输入寄存器可读,但不可写。
- * @param pucRegBuffer 返回数据指针
- * usAddress 寄存器起始地址
- * usNRegs 寄存器长度
- * @retval eStatus 寄存器状态
- */
- eMBErrorCode
- eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
- {
- eMBErrorCode eStatus = MB_ENOERR;
- int16_t iRegIndex;
-
- //查询是否在寄存器范围内
- //为了避免警告,修改为有符号整数
- if( ( (int16_t)usAddress >= REG_INPUT_START ) \
- && ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) )
- {
- //获得操作偏移量,本次操作起始地址-输入寄存器的初始地址
- iRegIndex = ( int16_t )( usAddress - usRegInputStart );
- //逐个赋值
- while( usNRegs > 0 )
- {
- //赋值高字节
- *pucRegBuffer++ = ( uint8_t )( usRegInputBuf[iRegIndex] >> 8 );
- //赋值低字节
- *pucRegBuffer++ = ( uint8_t )( usRegInputBuf[iRegIndex] & 0xFF );
- //偏移量增加
- iRegIndex++;
- //被操作寄存器数量递减
- usNRegs--;
- }
- }
- else
- {
- //返回错误状态,无寄存器
- eStatus = MB_ENOREG;
- }
- return eStatus;
- }
- /**
- * @brief 保持寄存器处理函数,保持寄存器可读,可读可写
- * @param pucRegBuffer 读操作时--返回数据指针,写操作时--输入数据指针
- * usAddress 寄存器起始地址
- * usNRegs 寄存器长度
- * eMode 操作方式,读或者写
- * @retval eStatus 寄存器状态
- */
- eMBErrorCode
- eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs,
- eMBRegisterMode eMode )
- {
- //错误状态
- eMBErrorCode eStatus = MB_ENOERR;
- //偏移量
- int16_t iRegIndex;
-
- //判断寄存器是不是在范围内
- if( ( (int16_t)usAddress >= REG_HOLDING_START ) \
- && ( usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS ) )
- {
- //计算偏移量
- iRegIndex = ( int16_t )( usAddress - usRegHoldingStart );
-
- switch ( eMode )
- {
- //读处理函数
- case MB_REG_READ:
- while( usNRegs > 0 )
- {
- *pucRegBuffer++ = ( uint8_t )( usRegHoldingBuf[iRegIndex] >> 8 );
- *pucRegBuffer++ = ( uint8_t )( usRegHoldingBuf[iRegIndex] & 0xFF );
- iRegIndex++;
- usNRegs--;
- }
- break;
- //写处理函数
- case MB_REG_WRITE:
- while( usNRegs > 0 )
- {
- usRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
- usRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
- iRegIndex++;
- usNRegs--;
- }
- break;
- }
- }
- else
- {
- //返回错误状态
- eStatus = MB_ENOREG;
- }
-
- return eStatus;
- }
- /**
- * @brief 线圈寄存器处理函数,线圈寄存器可读,可读可写
- * @param pucRegBuffer 读操作---返回数据指针,写操作--返回数据指针
- * usAddress 寄存器起始地址
- * usNRegs 寄存器长度
- * eMode 操作方式,读或者写
- * @retval eStatus 寄存器状态
- */
- eMBErrorCode
- eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils,
- eMBRegisterMode eMode )
- {
- //错误状态
- eMBErrorCode eStatus = MB_ENOERR;
- //寄存器个数
- int16_t iNCoils = ( int16_t )usNCoils;
- //寄存器偏移量
- int16_t usBitOffset;
- //检查寄存器是否在指定范围内
- if( ( (int16_t)usAddress >= REG_COILS_START ) &&
- ( usAddress + usNCoils <= REG_COILS_START + REG_COILS_SIZE ) )
- {
- //计算寄存器偏移量
- usBitOffset = ( int16_t )( usAddress - REG_COILS_START );
- switch ( eMode )
- {
- //读操作
- case MB_REG_READ:
- while( iNCoils > 0 )
- {
- *pucRegBuffer++ = xMBUtilGetBits( ucRegCoilsBuf, usBitOffset,
- ( uint8_t )( iNCoils > 8 ? 8 : iNCoils ) );
- iNCoils -= 8;
- usBitOffset += 8;
- }
- break;
- //写操作
- case MB_REG_WRITE:
- while( iNCoils > 0 )
- {
- xMBUtilSetBits( ucRegCoilsBuf, usBitOffset,
- ( uint8_t )( iNCoils > 8 ? 8 : iNCoils ),
- *pucRegBuffer++ );
- iNCoils -= 8;
- }
- break;
- }
- }
- else
- {
- eStatus = MB_ENOREG;
- }
- return eStatus;
- }
- eMBErrorCode
- eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
- {
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
|
评分
-
查看全部评分
|