2 Star 2 Fork 2

Actor_V / MF_Modbus

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
mf_mbevent.c 9.39 KB
一键复制 编辑 原始数据 按行查看 历史
myfuture 提交于 2022-06-10 16:56 . 优化写寄存器事件
#include "mf_mbevent.h"
#include "mf_mbcrc.h"
#include "mf_linklist.h"
#include "mf_mbport.h"
#include "mf_mbtime.h"
#include "mf_mb.h"
void mf_mb_event_send(void);
uint8_t mf_mb_event_read_get(uint8_t** data);
uint8_t mf_mb_event_write_get(uint8_t** data);
//modbus固定格式头
typedef struct
{
uint8_t slave_addr; //从站地址
uint8_t func_code; //功能码
}Mf_Mb_Head_t;
//读取事件链表头节点
mf_link* read_event_link = NULL;
//写入事件链表头节点
mf_link* write_event_link = NULL;
//事件发送时间
Mf_Mb_Time_t* send_poll_time = NULL;
//事件接收阻塞超时时间
Mf_Mb_Time_t* block_poll_time = NULL;
//当前正在发送的事件信息
Mf_Mb_Event_Now_t* mf_mb_event_tx_now = NULL;
//当前正在等待接收的事件信息
Mf_Mb_Event_Now_t* mf_mb_event_rx_now = NULL;
//临时发送事件复位
void mf_mb_event_tx_now_reset(void)
{
if(mf_mb_event_tx_now == NULL)
{
mf_mb_event_tx_now = (Mf_Mb_Event_Now_t*)malloc(sizeof(Mf_Mb_Event_Now_t));
}
if(mf_mb_event_tx_now->data != NULL) //非空时
{
if(mf_mb_event_tx_now->event_type == MF_MB_WRITE_EVENT) //如果是写入事件则销毁释放空间
{
free(mf_mb_event_tx_now->data);
}
mf_mb_event_tx_now->data = NULL;
}
mf_mb_event_tx_now->len = 0;
mf_mb_event_tx_now->lock = 0;
}
//临时接收事件复位
void mf_mb_event_rx_now_reset(void)
{
if(mf_mb_event_rx_now == NULL)
{
mf_mb_event_rx_now = (Mf_Mb_Event_Now_t*)malloc(sizeof(Mf_Mb_Event_Now_t));
}
if(mf_mb_event_rx_now->data != NULL) //非空时
{
mf_mb_event_rx_now->data = NULL;
}
mf_mb_event_rx_now->len = 0;
mf_mb_event_rx_now->lock = 0;
}
//事件功能初始化
void mf_mb_event_init(void)
{
//创建事件链表
read_event_link = link_create();
write_event_link = link_create();
//创建读取轮询时间计时
send_poll_time = mf_time_create(EVENT_SEND_POLL_TIME);
//开始时间轮询
mf_time_tick_start(send_poll_time);
//创建阻塞时间计时
block_poll_time = mf_time_create(EVENT_BLOCK_TIME);
mf_mb_event_tx_now_reset();
mf_mb_event_rx_now_reset();
}
//空闲状态下轮询等待发送
void mf_mb_event_idle_wait(void)
{
if(mf_time_get_trigger(send_poll_time))
{
mf_mb.mf_mb_state = MF_MB_MASTER_STATE_TX;
mf_time_tick_stop(send_poll_time);
}
}
//事件发送
void mf_mb_event_tx(void)
{
if(mf_mb_event_tx_now->data == NULL)
{
mf_mb_event_tx_now->len = mf_mb_event_write_get(&mf_mb_event_tx_now->data); //获得写入事件,优先级比读取事件高
if(mf_mb_event_tx_now->len == 0) //如果没有写入事件
{
mf_mb_event_tx_now->len = mf_mb_event_read_get(&mf_mb_event_tx_now->data); //获得读取事件
mf_mb_event_tx_now->event_type = MF_MB_READ_EVENT; //设定读取事件类型
}else //如果有写入事件类型
{
mf_mb_event_tx_now->event_type = MF_MB_WRITE_EVENT; //设定写入事件类型
}
}
if(mf_mb_event_tx_now->len > 0) //如果有事件类型
{
mf_mb_send_data(mf_mb_event_tx_now->data, mf_mb_event_tx_now->len); //调用发送接口发送
mf_mb.mf_mb_state = MF_MB_MASTER_STATE_TXEND; //发送完成后切换为发送完成状态
}else
{
mf_mb_event_rx_end(); //没有事件可发送,直接结束
}
}
//事件发送完成,预留接口,备用
void mf_mb_event_tx_end(void)
{
mf_mb.mf_mb_state = MF_MB_MASTER_STATE_RX; //切换为接收状态
mf_mb_event_rx_now_reset(); //发送完成后马上复位接收缓存,去除遗留接收干扰
mf_time_tick_start(block_poll_time); //开始阻塞超时计时
}
//事件应答接收
void mf_mb_event_rx(void)
{
if(mf_time_get_trigger(block_poll_time))
{
//超时没有收到数据
mf_mb.mf_mb_state = MF_MB_MASTER_STATE_RXERR; //切换为接收错误状态
//printf("超时没有收到数据\r\n");
}else
{
//printf("等待接收到数据\r\n");
if(mf_mb_event_rx_now->len > 4) //通过接收到数据的长度判断
{
//printf("收到%d数据长度\r\n",mf_mb_event_rx_now->len);
mf_mb_event_rx_now->lock = 1; //加锁
mf_time_tick_stop(block_poll_time); //停止阻塞超时计时
Mf_Mb_Head_t* event_rx_head = (Mf_Mb_Head_t*)mf_mb_event_rx_now->data;
Mf_Mb_Head_t* event_tx_head = (Mf_Mb_Head_t*)mf_mb_event_tx_now->data;
uint16_t rx_calc_crc = mf_mb_calc_crc(mf_mb_event_rx_now->data,mf_mb_event_rx_now->len - 2); //计算接收数据的CRC
uint16_t* rx_crc = (uint16_t*)&mf_mb_event_rx_now->data[mf_mb_event_rx_now->len - 2];
//printf("rx_calc_crc:%d,rx_crc:%d\r\n",rx_calc_crc,*rx_crc);
if(rx_calc_crc != *rx_crc) //判断CRC是否相同
{
mf_mb.mf_mb_state = MF_MB_MASTER_STATE_RXERR; //切换为接收错误状态
return;
}else if(event_rx_head->slave_addr != event_tx_head->slave_addr) //判断从机地址是否相同
{
mf_mb.mf_mb_state = MF_MB_MASTER_STATE_RXERR; //切换为接收错误状态
return;
}else if(event_rx_head->func_code != event_tx_head->func_code)//判断功能码是否相同
{
mf_mb.mf_mb_state = MF_MB_MASTER_STATE_RXERR; //切换为接收错误状态
return;
}
switch(event_rx_head->func_code)
{
case MF_MB_EVENT_FUNC_03: //03功能码
{
uint8_t byte8_size = *(mf_mb_event_rx_now->data + 2); //8位数据个数
uint16_t reg_addr = *((uint16_t*)(mf_mb_event_tx_now->data + 2)); //起始寄存器地址
uint8_t* byte8_data = mf_mb_event_rx_now->data + 3; //获得寄存器内容起始地址
mf_mb_03_data(event_tx_head->slave_addr,PTR2U16(&reg_addr),byte8_data,byte8_size);//触发回调
}break;
case MF_MB_EVENT_FUNC_04: //04功能码
{
uint8_t byte8_size = *(mf_mb_event_rx_now->data + 2); //8位数据个数
uint16_t reg_addr = *((uint16_t*)(mf_mb_event_tx_now->data + 2)); //起始寄存器地址
uint8_t* byte8_data = mf_mb_event_rx_now->data + 3; //获得寄存器内容起始地址
mf_mb_04_data(event_tx_head->slave_addr,PTR2U16(&reg_addr),byte8_data,byte8_size);//触发回调
}break;
case MF_MB_EVENT_FUNC_06: //06功能码
{
uint16_t reg_addr = *((uint16_t*)(mf_mb_event_tx_now->data + 2)); //起始寄存器地址
uint16_t* byte16_data = (uint16_t*)(mf_mb_event_rx_now->data + 4); //获得寄存器内容起始地址
mf_mb_06_data(event_tx_head->slave_addr,PTR2U16(&reg_addr),byte16_data); //触发回调
}break;
case MF_MB_EVENT_FUNC_10: //10功能码
{
}break;
default: mf_mb.mf_mb_state = MF_MB_MASTER_STATE_RXERR;break; //切换为接收错误状态
}
mf_mb.mf_mb_state = MF_MB_MASTER_STATE_RXEND;
mf_mb_event_rx_now->lock = 0; //解锁
}
}
}
//事件应答接收完成
void mf_mb_event_rx_end(void)
{
mf_mb.mf_mb_state = MF_MB_MASTER_STATE_IDLE; //切换为空闲状态
mf_time_tick_start(send_poll_time); //重新开启时间轮询
mf_mb_event_rx_now_reset(); //接收事件复位
mf_mb_event_tx_now_reset(); //发送事件复位
}
//事件接收错误
void mf_mb_event_rx_err(void)
{
static uint8_t err_count = 0; //重发次数
mf_time_tick_start(send_poll_time); //重新开启时间轮询
mf_mb.mf_mb_state = MF_MB_MASTER_STATE_IDLE; //切换为空闲状态
mf_mb_event_rx_now_reset(); //只复位接收事件
if(err_count++ > EVENT_REPE_NUM - 1) //计算重发次数
{
err_count = 0;
mf_mb_event_tx_now_reset(); //发送事件复位
}
}
//连续获得读取事件
//返回事件数据长度,0:没有事件
uint8_t mf_mb_event_read_get(uint8_t** data)
{
static mf_link* link = NULL;
if(link_get_length(read_event_link) == 0)
{
return 0;
}
if(link == NULL)
{
link = read_event_link->next;//第一个节点为空节点
}else
{
link = link->next;
if(link == read_event_link)
{
link = link->next;
}
}
*data = link->data;
return link->len;
}
//单次获得写入事件
//返回事件数据长度,0:没有事件
uint8_t mf_mb_event_write_get(uint8_t** data)
{
if(link_get_length(write_event_link) == 0)
{
return 0;
}
mf_link* link = write_event_link->next; //只取头节点的指向的下一个实际存在数据的节点
write_event_link->next = link->next;
*data = link->data;
free(link); //释放此节点空间
return link->len;
}
//读取事件添加
//返回事件首地址,NULL:添加失败
uint8_t* mf_mb_event_read_add(uint8_t slave_addr, uint8_t func_code, uint16_t reg_addr, uint16_t reg_num)
{
switch((Mf_Mb_Event_Func_code_e)func_code)
{
case MF_MB_EVENT_FUNC_03: //添加03读寄存器事件
{
Mf_Mb_ReadEvent_t* event = (Mf_Mb_ReadEvent_t*)malloc(sizeof(Mf_Mb_ReadEvent_t));
if(event == NULL) return 0;
event->slave_addr = slave_addr;
event->func_code = MF_MB_EVENT_FUNC_03;
event->reg_addr = PTR2U16(&reg_addr);
event->reg_num = PTR2U16(&reg_num);
event->crc = mf_mb_calc_crc((uint8_t*)event,sizeof(Mf_Mb_ReadEvent_t)-2);
link_tail_add(read_event_link,(uint8_t*)event,sizeof(Mf_Mb_ReadEvent_t));
return (uint8_t*)event;
}
case MF_MB_EVENT_FUNC_04: //添加04读寄存器事件
{
Mf_Mb_ReadEvent_t* event = (Mf_Mb_ReadEvent_t*)malloc(sizeof(Mf_Mb_ReadEvent_t));
if(event == NULL) return 0;
event->slave_addr = slave_addr;
event->func_code = MF_MB_EVENT_FUNC_04;
event->reg_addr = PTR2U16(&reg_addr);
event->reg_num = PTR2U16(&reg_num);
event->crc = mf_mb_calc_crc((uint8_t*)event,sizeof(Mf_Mb_ReadEvent_t)-2);
link_tail_add(read_event_link,(uint8_t*)event,sizeof(Mf_Mb_ReadEvent_t));
return (uint8_t*)event;
}
default:break;
}
return NULL;
}
//写入事件添加
//返回事件首地址,NULL:添加失败
uint8_t* mf_mb_event_write_add(uint8_t slave_addr, uint8_t func_code, uint16_t reg_addr, uint16_t* reg_data, uint8_t reg_num)
{
switch((Mf_Mb_Event_Func_code_e)func_code)
{
case MF_MB_EVENT_FUNC_06: //添加06写寄存器事件
{
Mf_Mb_WriteEvent_t* event = (Mf_Mb_WriteEvent_t*)malloc(sizeof(Mf_Mb_WriteEvent_t));
if(event == NULL) return NULL;
event->slave_addr = slave_addr;
event->func_code = MF_MB_EVENT_FUNC_06;
event->reg_addr = PTR2U16(&reg_addr);
event->reg_data = PTR2U16(reg_data);
event->crc = mf_mb_calc_crc((uint8_t*)event,sizeof(Mf_Mb_WriteEvent_t)-2);
link_tail_add(write_event_link,(uint8_t*)event,sizeof(Mf_Mb_WriteEvent_t));
return (uint8_t*)event;
}
case MF_MB_EVENT_FUNC_10: //添加10写多个寄存器事件
{
}
default:break;
}
return NULL;
}
C
1
https://gitee.com/Actor_V/mf_modbus.git
git@gitee.com:Actor_V/mf_modbus.git
Actor_V
mf_modbus
MF_Modbus
V1.0

搜索帮助