Pārlūkot izejas kodu

表头级联代码。

liyi 1 gadu atpakaļ
vecāks
revīzija
6b91f7130b

+ 720 - 0
f407/applications/cascade.c

@@ -0,0 +1,720 @@
+#include "cascade.h"
+#include "mb.h"
+#include "lock.h"
+#include "list.h"
+#include "modbus.h"
+#include <rtthread.h>
+#include <unistd.h>
+#include "pthread.h"
+#include "stdio.h"
+#include "string.h"
+#include "power.h"
+
+
+typedef struct {
+    uint8_t         cmd;
+    uint8_t         obj;
+    uint8_t         chId;
+    // char            time_s[24];   //start time
+    // char            time_e[24];   //end time
+		uint8_t 			data[200];
+}cmd_data_t;
+
+
+typedef void * handle_t;
+
+typedef struct {
+    mb_inst_t  *h;
+    uint8_t    mode;
+    uint8_t    type;
+}mb_conn_t;
+
+typedef struct {
+    mb_conn_t  rtu;
+    mb_conn_t  tcp;
+    
+    rt_thread_t tid;
+    uint8_t    quit;
+    
+    handle_t   rx;
+    handle_t   tx;
+    
+}mb_handle_t;
+
+typedef struct {
+    int       addr;
+    int       err;      //err times
+}slave_t;
+
+
+
+
+
+typedef struct cascade_info{
+	uint8_t  				saddr;
+	uint8_t 				md_type;
+	//void* 					list_ch;					//cascade_slave list
+	//cascade_data_t   cas_data;       
+	slave_info_t			info;
+	lock_t 					lock;
+	void*           mb;
+	slave_t         slaves[CASCADE_MAX+1];
+	cmd_data_t    cmd;
+	union {
+		md_ac_dc_t ac_dc;
+		md_3_ac_t  ac_3; 
+	}data;						//modbus to user
+}cascade_handle_t;
+
+static int mb_write_read(cascade_handle_t *cas, int addr, data_t *wd, data_t *rd);
+
+
+static cascade_handle_t slave_info = {0};
+
+uint8_t cascade_init(const char* uart,uint8_t mode,uint8_t addr,uint8_t baud)
+{	
+	list_cfg_t lc={0,LIST_FULL_FIFO,10};
+	mb_para_t para;
+	para.type = MB_TYPE_RTU;
+	para.para.rtu.dev = (char *)uart;
+	para.para.rtu.baudrate = baud;
+	para.para.rtu.parity = 2;
+	para.para.rtu.pin = -1;
+  para.para.rtu.lvl = 0;
+	if(addr == 0){
+		para.mode = MB_MODE_MASTER;
+	}else
+	{
+		para.mode = MB_MODE_SLAVE;
+		slave_info.saddr = addr;
+	}
+  slave_info.lock = lock_d_init();
+	slave_info.mb = mb_init(&para);
+  if(!slave_info.mb) {
+      return -1;
+  }
+	if(para.mode == MB_MODE_SLAVE)
+	{
+		mb_handle_t *handle = (mb_handle_t *)(slave_info.mb);
+		mb_set_slave(handle->rtu.h,slave_info.saddr);
+		//mb_set_cb_table();
+	}
+	//cas data
+	
+	return 0;
+}
+
+static uint8_t master_scan(cascade_handle_t *cas)
+{
+	static uint8_t slave_addr = 1;
+	if(slave_addr > CASCADE_MAX)
+	{
+		slave_addr = 1;
+	}
+	if(cas->slaves[slave_addr].addr == 0)
+	{
+		//scan
+		uint16_t value = 0;
+		lock_s_hold(cas->lock);
+		int r = mb_read(cas->mb,slave_addr,CASCADE_REG_SCAN,&value,1,300);
+		lock_s_release(cas->lock);
+		if(r > 0)
+		{
+			cas->slaves[slave_addr].addr = slave_addr;
+			cas->slaves[slave_addr].err = 0;
+			//获取当前
+		}
+	}
+	slave_addr++;
+}
+
+
+
+
+
+
+void * cascade_scan_thread(void *arg)
+{
+	while(1)
+	{
+		if(slave_info.md_type == MB_MODE_MASTER)
+		{
+			master_scan(&slave_info);
+		}
+		sleep(1);
+	}
+}
+
+static int slave_get_info(cascade_handle_t *cas)
+{
+	slave_info_t *info=&cas->info;
+	board_all_t *board = get_control_board();
+	info->channels = board->chs;
+	//info->channels=0;
+	//memcpy(info->ch,board->pbrd[],)
+	//copy mem to info
+	
+}
+
+
+static void* off_on_thread(void *arg)
+{
+	cascade_handle_t *cas=&slave_info;
+	cmd_data_t *pcmd=(cmd_data_t*)arg;
+	if(pcmd->cmd==CASCADE_CMD_OPEN) {
+     //   LOGD("____ slave CASCADE_CMD_OPEN\n");
+  }
+   else {
+   //     LOGD("____ slave CASCADE_CMD_CLOSE\n");
+    }
+	int flag=((pcmd->cmd==CASCADE_CMD_OPEN)?1:0);
+	if(pcmd->chId == 0xff) {
+		// all
+	}else
+	{
+		//one
+	}
+	 if(pcmd->cmd==CASCADE_CMD_OPEN) {
+     //   sprintf(temp,"$开启$|$所有$|$通道$");
+    }
+    else {
+     //   sprintf(temp,"$关闭$|$所有$|$通道$");
+    }
+		//data base
+		free(pcmd);
+		pthread_exit(NULL);
+}
+
+
+
+
+
+
+
+static int sendlen=0;
+
+
+
+void slave_func(uint16_t reg,void *r_w_data,uint32_t lenth)
+{
+	cmd_data_t *cmd=NULL;
+	mb_handle_t *handle = (mb_handle_t *)(slave_info.mb);
+	pthread_t id = 0;
+	switch (reg)
+	{
+		case CASCADE_REG_SCAN:
+
+		break;
+		case CASCADE_REG_WRITE:
+		{
+  
+			cmd = (cmd_data_t*)(r_w_data);
+      if(cmd->cmd>=CASCADE_CMD_GET_INFO) {
+					slave_info.cmd = *cmd;
+      }
+      sendlen = 0;
+      
+			switch(cmd->cmd)
+			{
+				case CASCADE_CMD_OPEN:
+        case CASCADE_CMD_CLOSE:
+				{
+					cmd_data_t *pcmd=malloc(sizeof(cmd_data_t));
+          if(pcmd) {
+            *pcmd = *cmd;
+						//thread_start_simp(cmd_thread, pcmd, 4*MB);
+						//pthread_create();
+						pthread_create(&id,NULL,off_on_thread,pcmd);
+						pthread_detach(id);
+          }
+				}
+					break;
+        case CASCADE_CMD_OPEN_NF:
+        case CASCADE_CMD_CLOSE_NF:
+				{
+				}
+					break;
+        case CASCADE_CMD_SAVE:
+        case CASCADE_CMD_SAVE3:
+				{
+				}
+					break;
+				case CASCADE_CMD_BREAKER_SAVE_ADD:
+				{
+				}
+					break;
+				case CASCADE_CMD_BREAKER_SAVE_UPDATE:
+				{
+				}
+					break;
+				case CASCADE_CMD_BREAKER_SAVE_DELETE:
+				{
+				}
+					break;
+			}
+		}
+		break;
+		case CASCADE_REG_READ:
+		{
+			cmd = &slave_info.cmd;
+			switch(cmd->cmd)
+			{
+				case CASCADE_CMD_GET_INFO:
+				{
+					slave_get_info(&slave_info);
+					memcpy(r_w_data,&slave_info.info+sendlen,lenth*2);
+				}
+					break;
+				case CASCADE_CMD_QUERY_CH:
+				{
+					slave_get_info(&slave_info);
+					memcpy(r_w_data,&slave_info.info+sendlen,lenth*2);
+				}
+					break;
+				case CASCADE_CMD_BREAKER_QUERY:
+					break;
+        case CASCADE_CMD_QUERY_VOL:break;
+        case CASCADE_CMD_QUERY_CUR:break;
+        case CASCADE_CMD_QUERY_PWR:break;
+        case CASCADE_CMD_QUERY_PWRQ:break;
+        case CASCADE_CMD_QUERY_HIS:break;
+        case CASCADE_CMD_QUERY_TOTAL:break;
+        case CASCADE_CMD_QUERY_TOTAL_PWR:break;
+        case CASCADE_CMD_BREAKER_GET_INFO:break;
+			}
+			sendlen += lenth*2;
+		}
+		break;
+		default:
+		{
+			
+		}
+		break;
+	}
+}
+
+#define REGS(x)    (((x)+(x)%2)/2)
+
+
+static int _mb_write(cascade_handle_t *cas, int addr, data_t *d)
+{
+	int i = 0,r=0,timeout=0;
+  int wl,xlen,wlen=0,oncelen=250;
+	uint16_t buff[MB_BUF_SIZE];
+	if(d->dlen<=0) {
+        return -1;
+  }
+	lock_d_hold(cas->lock);
+	while(1)
+	{
+		 if(wlen+oncelen>d->dlen) {
+			xlen = d->dlen-wlen;
+     } else 
+		 {
+       xlen = oncelen;
+     }
+		xlen += xlen%2;
+		memcpy(buff, d->data+wlen, xlen);
+		wl = mb_write(cas->mb, addr, CASCADE_REG_WRITE, buff, xlen/2);
+		if(wl<0) {
+			LOGE("___ _mb_write failed, addr: %d, reg: %d, cnt: %d, %s, retry: %d\n", addr, CASCADE_REG_WRITE, xlen/2,"write failed",i);
+      r = -1; 
+			break;
+    }
+		if(wlen+wl*2>=d->dlen) {
+      break;
+    }else {
+      xlen = wl*2;
+    }
+    wlen += xlen;
+	}
+	lock_d_release(cas->lock);
+}
+static int _mb_read(cascade_handle_t *cas, int addr, data_t *d)
+{
+    int i=0,r=0,finish=0,timeout=0;
+    int rl,xlen,rlen=0,oncelen=250;
+    uint16_t buff[MB_BUF_SIZE];	
+    if(d->dlen<=0) {
+        return -1;
+    }
+		lock_d_hold(cas->lock);
+    while(1) {
+			if(rlen+oncelen>d->dlen) {
+         xlen = d->dlen-rlen;
+      }else{
+         xlen = oncelen;
+      }
+      xlen += xlen%2;
+      rl = mb_read(cas->mb, addr, CASCADE_REG_READ, buff, xlen/2,500000);
+      if(rl<0) {
+        LOGE("___ _mb_read failed, %s, rlen: %d, retry: %d\n", "read error", rlen, i);
+        r = -1; break;
+      }
+      if(rlen+rl*2>=d->dlen) {
+        xlen = d->dlen-rlen;
+				finish = 1;
+      }else 
+			{
+        xlen = rl*2;
+      }
+
+      memcpy((char*)d->data+rlen, buff, xlen);
+      rlen += xlen;
+      if(finish) {
+         break;
+      }
+    }
+		
+}
+
+static int mb_write_read(cascade_handle_t *cas, int addr, data_t *wd, data_t *rd)
+{
+    int r=0;
+    
+    r = _mb_write(cas->mb, addr,wd);
+    if(r==0) {
+        r = _mb_read(cas->mb, addr,rd);
+    }
+    return r;
+}
+
+static int master_cmd(cascade_handle_t *cas,uint8_t cur_dev_addr ,cmd_data_t *cmd)
+{
+    int i,r;
+    data_t rdata,wdata;
+		
+    if(cur_dev_addr==0) {
+        return -1;
+    }
+
+    switch(cmd->cmd) {
+        case CASCADE_CMD_OPEN:
+        case CASCADE_CMD_CLOSE:
+        case CASCADE_CMD_SAVE:
+        case CASCADE_CMD_SAVE3:
+        case CASCADE_CMD_OPEN_NF:
+        case CASCADE_CMD_CLOSE_NF:
+        {
+            LOGD("____ master CMD: %d\n", cmd->cmd);
+
+            wdata.dlen = sizeof(cmd_data_t);
+            wdata.data = (uint8_t*)cmd;
+            r = _mb_write(cas, cur_dev_addr, &wdata);
+        }
+        break;
+
+        case CASCADE_CMD_GET_INFO:
+        {
+            wdata.dlen = sizeof(cmd_data_t);
+            wdata.data = (uint8_t*)cmd;
+
+            rdata.dlen = sizeof(slave_info_t)-sizeof(power_ch_t)*SLAVE_CH_MAX;
+            rdata.data = (uint8_t*)&cas->info;
+
+            r = mb_write_read(cas, cur_dev_addr, &wdata, &rdata);
+            if(r==0) {
+                //LOGD("______cas->info.cnt: %d\n", cas->sInfo.cnt);
+                rdata.dlen = sizeof(slave_info_t)-sizeof(power_ch_t)*(SLAVE_CH_MAX - cas->info.channels);
+                rdata.data = (uint8_t*)&cas->info;
+                r = mb_write_read(cas, cur_dev_addr, &wdata, &rdata);
+                if(r==0) {
+                    //power_add(cas);
+                }
+            }
+            else {
+                LOGE("_____ master CASCADE_CMD_GET_INFO failed\n");
+            }
+        }
+        break;
+        case CASCADE_CMD_BREAKER_GET_INFO:
+        {
+//            wdata.dlen = sizeof(cmd_data_t);
+//            wdata.data = (uint8_t*)cmd;
+//            rdata.dlen = sizeof(breaker_info_t)-sizeof(breaker_channel_info_t)*CH_MAX;
+//            rdata.data = (uint8_t*)&cas->sBreaker;
+//            LOGD("_____ master send CASCADE_CMD_BREAKER_GET_INFO\n");
+//            r = mb_write_read(cas, cur_dev_addr, &wdata, &rdata);
+//            if(r==0) {
+//                LOGD("______cas->info.cnt: %d\n", cas->sBreaker.cnt);
+//                rdata.dlen = sizeof(breaker_info_t)-sizeof(breaker_channel_info_t)*(CH_MAX-cas->sBreaker.cnt);
+//                rdata.data = (uint8_t*)&cas->sBreaker;
+//                r = mb_write_read(cas, cur_dev_addr, &wdata, &rdata);
+//                if(r==0) {
+//                   breaker_add(cas);
+//                }
+//            }
+        }
+        break;
+        case CASCADE_CMD_BREAKER_SAVE_UPDATE:
+        case CASCADE_CMD_BREAKER_SAVE_DELETE:
+        case CASCADE_CMD_BREAKER_SAVE_ADD:
+        {
+//            wdata.dlen = sizeof(cmd_data_t);
+//            wdata.data = (uint8_t*)cmd;
+//            r = mb_write(cas, cur_dev_addr, &wdata);
+        }
+        break;
+        default:
+        cas->cmd = *cmd;
+        r = 0;
+    }
+
+    return r;
+}
+
+
+static int master_query(cascade_handle_t *cas)
+{
+    int i,r;
+    cmd_data_t *cmd=&cas->cmd;
+    data_t rdata,wdata;
+
+    wdata.dlen = sizeof(cmd_data_t);
+    wdata.data = (uint8_t*)cmd;
+ 
+    switch(cmd->cmd) {
+
+        case CASCADE_CMD_QUERY_CH:
+        {
+
+            //LOGD("__00__ master query CASCADE_CMD_QUERY_CH, cnt: %d\n", cas->sInfo.cnt);
+            if(cas->info.channels==0 || cas->info.channels>SLAVE_CH_MAX) {
+                return -1;
+            }
+
+            rdata.dlen = sizeof(slave_info_t)-sizeof(power_ch_t)*(CH_MAX-cas->info.channels);
+            rdata.data = (uint8_t*)&cas->info;
+            
+            r = mb_write_read(cas, cas->saddr, &wdata, &rdata);
+            if(r==0) {
+                //power_update(cas);
+                cmd->cmd = CASCADE_CMD_BREAKER_QUERY;
+            }
+            else {
+                LOGE("____ master query CASCADE_CMD_QUERY_CH failed\n");
+            }
+            //LOGD("__11__ master query CASCADE_CMD_QUERY_CH, cnt: %d\n", cas->sInfo.cnt);
+        }
+        break;
+        case CASCADE_CMD_BREAKER_QUERY:
+        {
+            
+//            wdata.dlen = sizeof(cmd_data_t);
+//            wdata.data = (uint8_t*)cmd;
+//            rdata.dlen = sizeof(breaker_info_t)-sizeof(breaker_channel_info_t)*CH_MAX;
+//            rdata.data = (uint8_t*)&cas->sBreaker;
+//            r = mb_write_read(cas, cur_dev_addr, &wdata, &rdata);
+//            LOGD("____ master query CASCADE_CMD_BREAKER_QUERY, cnt: %d\n", cas->sBreaker.cnt);
+//            if(cas->sBreaker.cnt==0 || cas->sBreaker.cnt>CH_MAX)
+//            {
+//                breaker_clear(cas);
+//                cmd->cmd = CASCADE_CMD_QUERY_CH;
+//                return -1;
+//            }
+//            rdata.dlen = sizeof(breaker_info_t)-sizeof(breaker_channel_info_t)*(CH_MAX-cas->sBreaker.cnt);
+//            rdata.data = (uint8_t*)&cas->sBreaker;
+//            r = mb_write_read(cas, cur_dev_addr, &wdata, &rdata);
+//            if(r == 0)
+//            {
+//                breaker_add(cas);
+//                cmd->cmd = CASCADE_CMD_QUERY_CH;
+//            }else
+//            {
+//                LOGE("____ master query CASCADE_CMD_BREAKER_QUERY failed\n");
+//            }
+        }
+        break;
+        case CASCADE_CMD_QUERY_VOL:
+        {
+//            if(cmd->obj==OBJ_CHANNEL) {
+//                //rdata.dlen = sizeof(chInfo);
+//                //rdata.data = (uint8_t*)&chInfo;
+//            }
+//            else if(cmd->obj==OBJ_OVERALL) {
+//                //rdata.dlen = sizeof(chInfo);
+//                //rdata.data = (uint8_t*)&chInfo;
+//            }
+//            else {
+//                return -1;
+//            }
+        }
+        break;
+
+        case CASCADE_CMD_QUERY_CUR:
+        {
+//            if(cmd->obj==OBJ_CHANNEL) {
+//                //rdata.dlen = sizeof(chInfo);
+//                //rdata.data = (uint8_t*)&chInfo;
+//            }
+//            else if(cmd->obj==OBJ_OVERALL) {
+//                //rdata.dlen = sizeof(chInfo);
+//                //rdata.data = (uint8_t*)&chInfo;
+//            }
+//            else {
+//                return -1;
+//            }
+        }
+        break;
+
+        case CASCADE_CMD_QUERY_PWR:
+        {
+//            if(cmd->obj==OBJ_CHANNEL) {
+//                //rdata.dlen = sizeof(chInfo);
+//                //rdata.data = (uint8_t*)&chInfo;
+//            }
+//            else if(cmd->obj==OBJ_OVERALL) {
+//                //rdata.dlen = sizeof(chInfo);
+//                //rdata.data = (uint8_t*)&chInfo;
+//            }
+//            else {
+//                return -1;
+//            }
+        }
+        break;
+
+        case CASCADE_CMD_QUERY_PWRQ:
+        {
+//            if(cmd->obj==OBJ_CHANNEL) {
+//                //rdata.dlen = sizeof(chInfo);
+//                //rdata.data = (uint8_t*)&chInfo;
+//            }
+//            else if(cmd->obj==OBJ_OVERALL) {
+//                //rdata.dlen = sizeof(chInfo);
+//                //rdata.data = (uint8_t*)&chInfo;
+//            }
+//            else {
+//                return -1;
+//            }
+        }
+        break;
+
+        case CASCADE_CMD_QUERY_HIS:
+        {
+//            if(cmd->obj==OBJ_CHANNEL) {
+//                //rdata.dlen = sizeof(chInfo);
+//                //rdata.data = (uint8_t*)&chInfo;
+//            }
+//            else if(cmd->obj==OBJ_OVERALL) {
+//                //rdata.dlen = sizeof(chInfo);
+//                //rdata.data = (uint8_t*)&chInfo;
+//            }
+//            else {
+//                return -1;
+//            }
+        }
+        break;
+
+        case CASCADE_CMD_QUERY_TOTAL:
+        {
+//            if(cmd->obj==OBJ_CHANNEL) {
+//                //rdata.dlen = sizeof(chInfo);
+//                //rdata.data = (uint8_t*)&chInfo;
+//            }
+//            else if(cmd->obj==OBJ_OVERALL) {
+//                //rdata.dlen = sizeof(chInfo);
+//                //rdata.data = (uint8_t*)&chInfo;
+//            }
+//            else {
+//                return -1;
+//            }
+        }
+        break;
+
+        case CASCADE_CMD_QUERY_TOTAL_PWR:
+        {
+//            if(cmd->obj==OBJ_CHANNEL) {
+//                //rdata.dlen = sizeof(chInfo);
+//                //rdata.data = (uint8_t*)&chInfo;
+//            }
+//            else if(cmd->obj==OBJ_OVERALL) {
+//                //rdata.dlen = sizeof(chInfo);
+//                //rdata.data = (uint8_t*)&chInfo;
+//            }
+//            else {
+//                return -1;
+//            }
+        }
+        break;
+
+        default:
+        //LOGD("____ master query cmd: %d\n", cmd->cmd);
+        return -1;
+    }
+
+    return r;
+}
+
+
+int mb_port_read_disc(u16 addr, u8 *pbit)//读离散量输入, 返回 : 0-成功, -2-地址错误
+{
+    MB_ASSERT(pbit != NULL);
+    
+    return(-2);
+}
+
+int mb_port_read_coil(u16 addr, u8 *pbit)//读线圈, 返回 : 0-成功, -2-地址错误
+{
+    MB_ASSERT(pbit != NULL);
+    
+    return(-2);
+}
+
+int mb_port_write_coil(u16 addr, u8 bit)//写线圈, 返回 : 0-成功, -2-地址错误, -4-设备故障
+{
+    return(-2);
+}
+
+int mb_port_read_input(u16 addr, u16 *preg)//读输入寄存器, 返回 : 0-成功, -2-地址错误
+{
+    MB_ASSERT(preg != NULL);
+    
+    return(-2);
+}
+
+int mb_port_read_hold(u16 addr, u16 *preg)//读保持寄存器, 返回 : 0-成功, -2-地址错误
+{
+    MB_ASSERT(preg != NULL);
+		uint16_t *data = NULL;
+    if( AC_DC_DEV_CHN_REG <= addr &&  addr <= AC_DC_DRY_REG)
+		{
+			data = (uint16_t*)(&slave_info.data.ac_dc);
+			uint32_t offset = addr - AC_DC_DEV_CHN_REG;
+			*preg = *(data+offset);
+			return 0;
+		}
+		if(AC_3_DEV_CHN_REG <= addr && addr <= AC_3_DRY_REG)
+		{
+			data = (uint16_t*)(&slave_info.data.ac_3);
+			uint32_t offset = addr - AC_DC_DEV_CHN_REG;
+			*preg = *(data+offset);
+			return 0;
+		}	
+		return(-2);
+}
+
+int mb_port_write_hold(u16 addr, u16 reg)//写保持寄存器, 返回 : 0-成功, -2-地址错误, -3-值非法, -4-设备故障
+{
+	board_all_t *board = get_control_board();
+  if(AC_DC_SET_DELAY_OPEN <= addr && addr <= AC_DC_ALL_SET_SWITCH_REG)
+	{
+		switch(addr)
+		{
+			case AC_DC_SET_DELAY_OPEN ... (AC_DC_SET_DELAY_CLOSE-1):
+			{
+				uint16_t channel = addr - AC_DC_SET_DELAY_OPEN;
+				//获取通道控制接口 写入数据
+				
+				
+			}
+			break;
+		}
+		return 0;
+	}
+	return(-2);
+} 
+
+
+
+
+

+ 93 - 0
f407/applications/cascade.h

@@ -0,0 +1,93 @@
+#ifndef _CASCADE_H_
+#define _CASCADE_H_
+
+
+
+
+#include "datadef.h"
+
+
+
+typedef struct {
+    int             dlen;
+    uint8_t         *data;           
+}data_t;
+
+
+
+
+
+#define AC_DC_DEV_CHN_REG                  	(4000)
+#define AC_DC_DRY_REG         							(4987)
+
+#define AC_DC_SET_DELAY_OPEN								(5000)
+#define AC_DC_SET_DELAY_CLOSE								(5064)
+#define AC_DC_CHN_SET_SWITCH_STA_REG        (5128)
+#define AC_DC_ALL_SET_SWITCH_REG        		(5192)
+
+
+
+
+#define AC_3_DEV_CHN_REG                  	(6000)
+#define AC_3_DRY_REG           							(8795)
+
+
+#define AC_3_SET_DELAY_OPEN									(9000)
+#define AC_3_SET_DELAY_CLOSE								(9064)
+#define AC_3_CHN_SET_SWITCH_STA_REG        	(9128)
+#define AC_3_ALL_SET_SWITCH_REG        			(9192)
+
+
+
+
+
+
+
+
+
+
+#define CASCADE_REG_OFFSET              0x10
+#define CASCADE_REG_READ                (CASCADE_REG_OFFSET+0)
+#define CASCADE_REG_WRITE               (CASCADE_REG_OFFSET+1)
+#define CASCADE_REG_SCAN                (CASCADE_REG_OFFSET+2)
+
+
+
+enum {
+    CASCADE_CMD_OPEN=0,
+    CASCADE_CMD_CLOSE,
+    CASCADE_CMD_SAVE,
+    CASCADE_CMD_SAVE3,
+
+    CASCADE_CMD_GET_INFO,
+
+    CASCADE_CMD_QUERY_CH,
+    CASCADE_CMD_QUERY_VOL,
+    CASCADE_CMD_QUERY_CUR,
+    CASCADE_CMD_QUERY_PWR,
+    CASCADE_CMD_QUERY_PWRQ,
+    CASCADE_CMD_QUERY_HIS,
+    CASCADE_CMD_QUERY_TOTAL,
+    CASCADE_CMD_QUERY_TOTAL_PWR,
+
+    CASCADE_CMD_BREAKER_QUERY,
+    CASCADE_CMD_BREAKER_GET_INFO,
+    CASCADE_CMD_BREAKER_SAVE_ADD,
+    CASCADE_CMD_BREAKER_SAVE_UPDATE,
+    CASCADE_CMD_BREAKER_SAVE_DELETE,
+    CASCADE_CMD_OPEN_NF,
+    CASCADE_CMD_CLOSE_NF,
+
+    CASCADE_CMD_MAX,
+};
+
+
+
+
+
+
+
+uint8_t cascade_init(const char* uart,uint8_t mode,uint8_t addr,uint8_t baud);
+uint8_t cascade_deinit();
+
+#endif

+ 10 - 4
f407/applications/datadef.h

@@ -7,6 +7,7 @@
 
 #define CH_MAX          12
 #define BRD_MAX         32
+#define SLAVE_CH_MAX    64
 
 enum{
     A_P = 0,
@@ -42,6 +43,11 @@ enum {
     PDU_AC_I3O3_H,
 };
 
+enum {
+    BOARD_TYPE_DC=0,
+    BOARD_TYPE_AC,
+    BOARD_TYPE_AC3,
+};
 
 enum {
     ALARM_TYPE_POWER=0,
@@ -361,13 +367,13 @@ typedef struct {
 typedef struct cascade_saddr{
     uint8_t      addr;
     uint16_t     channels;
-    board_fn_t   *fn;
-    power_ch_t   ch[];
-}cascade_saddr_t;
+    //board_fn_t   *fn;
+    power_ch_t   ch[SLAVE_CH_MAX];
+}slave_info_t;
 
 
 typedef struct cascade_data{
-    cascade_saddr_t *c_s[BRD_MAX];                        //从机最多个数
+    slave_info_t *c_s[BRD_MAX];                        //从机最多个数
 }cascade_data_t;
 
 

+ 12 - 0
f407/applications/packages/qmodbus-latest/inc/modbus.h

@@ -41,6 +41,11 @@ typedef struct{
     mb_write_reg_t  write_hold; //写保持寄存器
 }mb_cb_table_t;
 
+typedef struct mb_cascade_fun{
+	void (*slave_func)(uint16_t reg,void* r_w_data,uint32_t lenth);
+}mb_cascade_fun_t;
+
+
 typedef struct{
     u8 saddr;               //从机地址
     mb_prot_t prot;         //通信协议
@@ -49,8 +54,15 @@ typedef struct{
     mb_cb_table_t *cb;      //从机回调函数表
     u8 datas[256];          //读写数据缓冲区
     u8 buf[MB_BUF_SIZE];    //收发缓冲区
+		mb_cascade_fun_t *func;		//other func
 }mb_inst_t;
 
+
+
+
+
+
+
 //创建modbus实例, 成功返回实例指针, 失败返回NULL
 mb_inst_t * mb_create(mb_backend_type_t type, const mb_backend_param_t *param);
 //销毁modbus实例

+ 1 - 1
f407/applications/packages/qmodbus-latest/src/modbus_port_slave.c

@@ -45,7 +45,7 @@ MB_WEAK int mb_port_read_hold(u16 addr, u16 *preg)//读保持寄存器, 返回 :
 MB_WEAK int mb_port_write_hold(u16 addr, u16 reg)//写保持寄存器, 返回 : 0-成功, -2-地址错误, -3-值非法, -4-设备故障
 {
     return(-2);
-}
+} 
 #endif
 
 

+ 43 - 25
f407/applications/packages/qmodbus-latest/src/modbus_slave.c

@@ -83,19 +83,24 @@ static void mb_slave_pdu_deal_read_holds(mb_inst_t *hinst, mb_pdu_t *pdu)
     u16 addr = pdu->rd_req.addr;
     int nb = pdu->rd_req.nb;
     u8 *p = hinst->datas;
-    for (int i=0; i<nb; i++)
-    {
-        u16 val;
-        int rst = hinst->cb->read_hold(addr + i, &val);
-        if (rst < 0)
-        {
-            pdu->exc.ec = -rst;
-            pdu->exc.fc = MODBUS_FC_EXCEPT_MAKE(pdu->exc.fc);
-            return;
-        }
-        p += mb_cvt_u16_put(p, val);
-    }
-    
+		if(addr < 0x20)
+		{
+			hinst->func->slave_func(addr,p,nb);	// 读回调函数
+		}else
+		{
+				for (int i=0; i<nb; i++)
+				{
+						u16 val;
+						int rst = hinst->cb->read_hold(addr + i, &val);
+						if (rst < 0)
+						{
+								pdu->exc.ec = -rst;
+								pdu->exc.fc = MODBUS_FC_EXCEPT_MAKE(pdu->exc.fc);
+								return;
+						}
+						p += mb_cvt_u16_put(p, val);
+				}
+		}
     pdu->rd_rsp.dlen = 2 * nb;
     pdu->rd_rsp.pdata = hinst->datas;
 }
@@ -212,18 +217,24 @@ static void mb_slave_pdu_deal_write_regs(mb_inst_t *hinst, mb_pdu_t *pdu)
     u16 addr = pdu->wr_req.addr;
     int nb = pdu->wr_req.nb;
     u8 *p = pdu->wr_req.pdata;
-    for (int i=0; i<nb; i++)
-    {
-        u16 val;
-        p += mb_cvt_u16_get(p, &val);
-        int rst = hinst->cb->write_hold(addr + i, val);
-        if (rst < 0)
-        {
-            pdu->exc.ec = -rst;
-            pdu->exc.fc = MODBUS_FC_EXCEPT_MAKE(pdu->exc.fc);
-            return;
-        }
-    }
+		if(addr < 0x20)
+		{
+			hinst->func->slave_func(addr,p,nb);
+		}else
+		{
+			for (int i=0; i<nb; i++)
+			{
+					u16 val;
+					p += mb_cvt_u16_get(p, &val);
+					int rst = hinst->cb->write_hold(addr + i, val);
+					if (rst < 0)
+					{
+							pdu->exc.ec = -rst;
+							pdu->exc.fc = MODBUS_FC_EXCEPT_MAKE(pdu->exc.fc);
+							return;
+					}
+			}
+		}
 }
 
 static void mb_slave_pdu_deal_mask_write_reg(mb_inst_t *hinst, mb_pdu_t *pdu)
@@ -452,6 +463,13 @@ void mb_set_cb_table(mb_inst_t *hinst, const mb_cb_table_t *cb)
     hinst->cb = (mb_cb_table_t *)cb;
 }
 
+void mb_set_cb_cascade(mb_inst_t *hinst, const mb_cascade_fun_t *func)
+{
+	  MB_ASSERT(hinst != NULL);
+    MB_ASSERT(func != NULL);
+		hinst->func = (mb_cascade_fun_t *)func;
+}
+
 //从机状态机处理, 在线程中循环调用即可
 void mb_slave_fsm(mb_inst_t *hinst)
 {

+ 1 - 0
f407/applications/power.h

@@ -159,5 +159,6 @@ int power_scan(int max_addr);
 int power_get_ch(int ch, power_ch_t *pch);
 int power_get_board(int addr, board_data_t *pb);
 
+board_all_t * get_control_board();
 #endif