123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276 |
- #include "board.h"
- #include "poweroff_save_app.h"
- #include "modbus_encoder.h"
- #include "modbus_slave.h"
- #include "modbus_master.h"
- #include "variable.h"
- #include "SEGGER_RTT.h"
- #include "encrypt_md5.h"
- #include "encrypt_xxtea.h"
- #include "modbus_app.h"
- #include <string.h>
- #define MODBUS_APP_NUMBER 3
- typedef struct
- {
- unsigned char uart_no; //串口号
- unsigned char modbus_dir; //modbus方向,0是从机,1是主机
- //当做为从机时,master_or_slave保存modbus_slave_t 对象指针
- //当做为主机时,master_or_slave保存modbus_master_t 对象指针
- void *master_or_slave; //主站信息
- unsigned char count;
- unsigned char step; //状态步
- unsigned char rx_buffer[1024];
- unsigned char tx_buffer[512];
- } modbus_status_t;
- //modbus主站对象信息
- modbus_master_t master1;
- static modbus_slave_t slaves[2];
- void servo_on_respone(modbus_master_cmd_t *cmd, unsigned char *respone, int length);
- //modbus协议的一些状态信息
- static modbus_status_t modbus_status[MODBUS_APP_NUMBER] = {
- { 0, 0, &slaves[0] ,2}, //组0,ID2,串口2,从站
- //{ 2, 0, &slaves[0] ,2}, //组0,ID2,串口2,从站
- { 1, 0, &slaves[0] ,2}, //组1,ID1,串口3主站
- { 3, 1, &master1 ,1}
- };
- /**
- * 系统默认的回调函数
- *
- * @author lxz (2019/6/12/周三)
- *
- * @param address
- * @param number
- */
- static void slave1_on_comm(unsigned char id, unsigned char cmd, unsigned short address, unsigned short number)
- {
- //通知软件需要退出进入bootloader
- if (cmd == 0x23)
- {
- extern void app_save_parameter(void);
- //先保存参数
- app_save_parameter();
- //设置标志位
- //Stm32_Clock_DeInit();
- //设置标志
- hw_noinit_write(0, 0xA5A5A5A5);
- //设置ID
- hw_noinit_write(3, id);
- hw_noinit_write(2, 115200);
- hw_noinit_write(4, 115200);
- hw_noinit_write(6, 115200);
- hw_board_reboot();
- }
- }
- /**
- * modbus应用环境的初始化,包括了一些数据域的初始化注册
- *
- * @author lxz (2019/5/17/周五)
- */
- void mosbus_app_init(void)
- {
- modbus_slave_t *slave = &slaves[0];
- //保存ID码,保证bootloader会同步回来
- hw_noinit_write(1, 1);
- hw_noinit_write(3, 1);
- hw_noinit_write(5, 1);
- //从站初始化
- memset(&slaves[0], 0, sizeof(slaves));
- slave->id = 1; //设置从站ID
- slave->on_comm = slave1_on_comm; //设置从站通讯的回调函数
- //添加从站有效的数据域信息
- modbus_slave_add_dataarea(slave,
- 0x01, //数据类型为位
- 0, //映射开始地址为0
- MIDDLE_COILS_NUMBER, //数据单位个数
- (unsigned char *)&middle_coils[0] //数据所在地址
- );
- modbus_slave_add_dataarea(slave,
- 0x01, //数据类型为位
- 0x0800, //映射开始地址为0x800,用于兼容台达DVP协议的M码地址
- MIDDLE_COILS_NUMBER, //数据单位个数
- (unsigned char *)&middle_coils[0] //数据所在地址
- );
- modbus_slave_add_dataarea(slave,
- 0x03, //数据类型为16位数值
- 0, //映射开始地址为0
- USER_DATA_NUMBER, //数据单位个数
- (unsigned char *)&user_datas[0] //数据所在地址
- );
- modbus_slave_add_dataarea(slave,
- 0x03, //数据类型为16位数值
- 0x1000, //映射开始地址为0x1000,用于兼容台达DVP协议的D码地址
- USER_DATA_NUMBER, //数据单位个数
- (unsigned char *)&user_datas[0] //数据所在地址
- );
- //升级系统必须的命令
- modbus_slave_add_dataarea(slave,
- 0xFE, //数据类型为系统定制,升级时使用
- 0, //映射开始地址为0
- 512, //数据单位个数
- 0 //数据所在地址
- );
- //WIFI一些对应的通讯缓冲
- slave = &slaves[1];
- slave->id = 0x7F;
- modbus_slave_add_dataarea(slave,
- 0x01, //数据类型为系统定制,升级时使用
- 0x00, //映射开始地址为0
- 24, //数据单位个数
- (unsigned char *)&middle_coils[1000 >> 3] //数据所在地址
- );
- modbus_slave_add_dataarea(slave,
- 0x03, //数据类型为系统定制,升级时使用
- 0x00, //映射开始地址为0
- 128, //数据单位个数
- (unsigned char *)&user_datas[1600] //数据所在地址
- );
- #if 1
- //初始化主站环境
- modbus_master_init();
- //初始化主站信息
- memset(&master1, 0, sizeof(master1));
- master1.encoder_type = MODBUS_ENCODER_RTU; //RTU模式
- master1.interval = 10000; //10ms的命令间隔
- master1.one_byte_time = 1000; //一个字节的时间为1ms
- master1.retry = 3; //命令的重试次数为3次
- #endif
-
- }
- /**
- * modbus 从台应用代码
- *
- * @author lxz (2019/5/17/周五)
- *
- * @param status
- */
- static void modbus_slave_app(modbus_status_t *status)
- {
- int length;
- int index = 0;
- modbus_encoder_t *encoder;
- switch (status->step)
- {
- case 0:
- hw_dma_uart_begin_read(status->uart_no, &status->rx_buffer[0], 1024);
- status->step++;
- break;
- case 1:
- length = hw_dma_uart_read_finish(status->uart_no);
- if (length > 0)
- {
- status->step = 0;
- encoder = modbus_encoder_match(status->rx_buffer, length);
- if (encoder != (void *)0)
- {
- length = encoder->decode(&status->rx_buffer[0], &status->rx_buffer[0], length);
- if (length > 0)
- {
- while (index < status->count)
- {
- length = modbus_slave_run(
- &((modbus_slave_t *)status->master_or_slave)[index],
- &status->tx_buffer[0],
- &status->rx_buffer[0]);
- if (length > 0)
- {
- length = encoder->encode(&status->tx_buffer[0], &status->tx_buffer[0], length);
- if (length > 0)
- {
- hw_dma_uart_begin_write(status->uart_no, (const char *)&status->tx_buffer[0], length);
- status->step = 2;
- }
- break;
- }
-
- index++;
- }
- }
- }
- }
- break;
- case 2:
- if (hw_dma_uart_write_finish(status->uart_no))
- {
- status->step = 0;
- }
- break;
- }
- }
- /**
- * 主站应用代码
- *
- * @author lxz
- *
- * @param status
- */
- static void modbus_master_app(modbus_status_t *status)
- {
- int length;
- switch (status->step)
- {
- case 0:
- //判断是否有包需要处理
- length = hw_dma_uart_read_finish(status->uart_no);
- //将接收信息提供给主站,并获取主站输出
- length = modbus_master_run(
- (modbus_master_t *)status->master_or_slave,
- status->tx_buffer,
- status->rx_buffer,
- length);
- if (length > 0)
- {
- //主站有需要输出时进行输出
- hw_dma_uart_begin_write(status->uart_no, (const char *)&status->tx_buffer[0], length);
- status->step++;
- }
- break;
- case 1:
- //等待输出完毕
- if (hw_dma_uart_write_finish(status->uart_no))
- {
- status->step = 0;
- hw_dma_uart_begin_read(status->uart_no, &status->rx_buffer[0], 1024);
- }
- break;
- }
- }
- /**
- * modbus应用的循环运行函数,根据自己需求编写
- *
- * @author lxz (2019/5/17/周五)
- *
- * @param void
- */
- void modbus_app_proc(void)
- {
- int index = 0;
- while (index < MODBUS_APP_NUMBER)
- {
- if (modbus_status[index].modbus_dir == 0)
- {
- modbus_slave_app(&modbus_status[index]);
- } else
- {
- modbus_master_app(&modbus_status[index]);
- }
- index++;
- }
- }
|