本文主要是介绍智能离网微逆变系统,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 一、功能描述
- 二、硬件部分
- 2.1、单片机选型及中断号
- 2.1.1、引脚分配
- 2.2、EG8010
- 2.3、控制电路图
- 2.4、主电路图
- 三、代码流程图
- 四、代码部分展示
- 4.1、主函数
- 4.2、modbus
- 五、项目演示
一、功能描述
- 把风光能,逆变为可调压调频的交流电
- 可通过串口屏,PLC,以太网等调整及显示电压频率
- 串口屏:显示电压波形,修改电压频率,开机及修改次数
- PLC:修改电压频率
- 以太网:修改电压频率
二、硬件部分
2.1、单片机选型及中断号
2.1.1、引脚分配
2.2、EG8010
- EG8010 是一款数字化的、功能很完善的自带死区控制的纯正弦波逆变发生器芯片,应用于 DC-DC-AC 两
级功率变换架构或 DC-AC 单级工频变压器升压变换架构,外接 12MHz 晶体振荡器,能实现高精度、失真和
谐波都很小的纯正弦波 50Hz 或 60Hz 逆变器专用芯片。该芯片采用 CMOS 工艺,内部集成 SPWM 正弦发生器、
死区时间控制电路、幅度因子乘法器、软启动电路、保护电路、RS232 串行通讯接口和 12832 串行液晶驱动
模块等功能。
2.3、控制电路图
- 保护检测,光耦隔离,AD采样,eg8010,sg3525
- IAP15W4K61S4(STC15系列单片机)
- RS232:串口1 RXD:P3.0 TXD:P3.1
- 串口屏:串口2 RXD2:P1.0 TXD2:P1.1
- EG8010:串口3 RXD3:P0.0 TXD2:P0.1
- RS485:串口4 RXD4:P0.2 TXD4:P0.3 485_EN:P0.4
- wifi:模拟串口 RXB:P3.6 TXB:P3.7
- 故障指示灯:LED1-LED4 P4.1-P4.4
- 故障信号检测:Fault1-Fault4 P2.0-P2.3
- 输出电压检测:U ADIn:P1.7
- 输出电流检测:U ADIn:P1.6
- eg8010
- 6脚使能信号
- 7脚风扇
- 4.5脚通信
- 1.2脚死区时间调整
- 9脚正极性脉冲调制方法
- spwm脉冲,单极,性双极性调制方法
- 10.11脚晶振
- 13.14.15反馈输入
- 18.19频率选择
- 20调制方法选择
- 21软起动
- 27-30SPWM输出
- IR2110S:SPWM隔离放大5-15v
- 兼有光耦隔离和电磁隔离的优点,是中小功率变换装置中驱动器件的首选
- SG3525
- 驱动N沟道功率MOSFET,是一种性能优良、功能齐全、通用性强的单片集成PWM控制芯片,输出驱动为推拉输出形式,增加了驱动能力;内部含有欠压锁定电路、软启动控制电路、PWM锁存器,有过流保护功能,频率可调,能限制最大占空比
- 电流控制型PWM控制器,所谓电流控制型脉宽调制器是按照接反馈电流来调节脉宽的。在脉宽比较器的输入端直接用流过输出电感线圈的信号与误差放大器输出信号进行比较,从而调节占空比使输出的电感峰值电流跟随误差电压变化而变化。由于结构上有电压环和电流环双环系统,因此,无论开关电源的电压调整率、负载调整率和瞬态响应特性都有提高,是目前比较理想的新型控制器。
原文链接:https://blog.csdn.net/weixin_42341666/article/details/100046363
- 保护检测电路
- Batt_I,前级过流保护
- HVOv_Vol,母线过压
- BattUn_Vol,欠压(风光能20v)
- BattOv_Vol,过压(风光能28v)
2.4、主电路图
-
前级升压:
- 由SG3525发出PWM
- PWM控制芯片,输出驱动为推拉输出形式,增加了驱动能力;内部含有欠压锁定电路、软启动控制电路、PWM锁存器,有过流保护功能,频率可调,能限制最大占空比。
- 变压器升压
- 二极管整流
- 电容滤波
- 由SG3525发出PWM
-
后级逆变
- EG8010产生SPWM逆变
- 等幅不等宽方波,等效正弦波
- 面积等效原理
- EG8010产生SPWM逆变
-
直流供电电压降压
- 24转12
- 24转15
- 15转5
-
PC817
- 光耦隔离
- 给SG3525(1,9脚输入信号)
与引脚1间接电阻电容构成PI调节器
-
母线过压信号检测
-
电压,电流采样AD值
-
VFB,IFB,TFB
- EG8010反馈输入信号
三、代码流程图
-
代码共1075行
-
主函数流程图
- 模拟串口流程图
四、代码部分展示
4.1、主函数
#include "main.h"
#include "uart.h"
#include "send_eg.h"
#include "modbus.h"
#include "wifi.h"
#include "EEPROM.h"void port_mode(void) // I/O口模式设置
{P0M1 = 0x00; P0M0 = 0x10; //P0.4--485控制引脚 强推挽输出,,,,,\\enP1M1 = 0xc0; P1M0 = 0x00; //P1.6 P1.7--ADC采集口高阻输入模式,\\I_ADIn,U_ADInP2M1 = 0xff; P2M0 = 0x00; //P2 高阻输入模式 \\4 NLFault 不需要采集ad,大概率不需要初始化P3M1 = 0x00; P3M0 = 0x00; //准双向口! 可以不写,因为默认模式P4M1 = 0x00; P4M0 = 0xff; //强推挽输出\\4 led led基本不需要强推晚
}
void delay_us(u16 n)
{do{n--;}while(n);
}void delay_ms(u16 n)
{do{delay_us(900); }while(--n);
}void main()
{u8 i=0;u8 buffer[50],len;//串口屏数据处理用port_mode();Uart2_init();//串口屏Uart3_init();//eg8050RS485_init();//485Timer0Init();//1msInitADC(); //AD初始化UART_INIT(); //wifi初始化EEPROM_Read(); //读邋邋邋EEPROM,读电压,频率,开机次数delay_ms(10);kjc++; //开机次数+1SetTextValue(0,14,dyc);//串口屏显示电压SetTextValue(0,14,dyc);//串口屏显示电压,写一次显示不出来,可能需要SetTextValue(0,15,plc);SetTextValue(0,13,kjc);delay_ms(10);EEPROM_Write(); //电压,频率,开机次数,写入EEPROMEG_OUTPL(0);while(1){Curve_Show();//曲线,电压电流,峰谷值check_modbus();//485判断是否收到数据,然后去处理Wifi_Ctrl(); //网络控制输出if(i==255){ //queue_find_cmd(buffer,50); 延时作用,因为串口屏数据接收需要一定时间,不加延时可能读不到完整数据i=0;EG8010_ctr();//频率, 电压值是通过ad采样(虽然eg也可以读取电压,但是还是使用ad更为稳妥)len = queue_find_cmd(buffer,50); //取串口屏发送的一帧数据,有返回数据长度,没有完整数据返回0if(len>0){ProcessMessage((PCTRL_MSG)buffer);//处理一帧数据len=0;memset(buffer,'\0',50); //清空buffer}}i++;}
}
4.2、modbus
#include "modbus.h"
unsigned char sendBuf[50];const unsigned char code auchCRCHi[] = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0/**/,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
} ;
/* CRC低位字节值表*/
const unsigned char code auchCRCLo[] = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06/**/,
0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
0x43, 0x83, 0x41, 0x81, 0x80, 0x40
} ;
/****************************************************
/**************CRC校验码生成函数 ***************/
unsigned int CRC16_Check(unsigned char *puchMsg,unsigned int usDataLen)//CRC16校验
{unsigned char uchCRCHi = 0xFF ; /* 高CRC字节初始化 */ unsigned char uchCRCLo = 0xFF ; /* 低CRC 字节初始化 */ unsigned int uIndex ; /* CRC循环中的索引 */ while (usDataLen--) /* 传输消息缓冲区 */ { uIndex = uchCRCHi ^ *puchMsg++ ; /* 计算CRC */ uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ; uchCRCLo = auchCRCLo[uIndex] ; } return (uchCRCLo << 8 | uchCRCHi) ;
}
void RS485_init()//485初始化
{Uart4_init();EN_485 = 0;//接收状态
}
void RS485_Send(unsigned char *p,unsigned char len)//485发送字符串
{unsigned char i;EN_485 = 1; //处于发送for(i=0;i<len;i++) //循环发送所有数据Uart4_SendData(p[i]);//发送单个数据EN_485 = 0; //发送完后将485置于接收状态receCount = 0; //清接收地址偏移寄存器
}
//------------------------------------定时处理--------------------------------
void timeProc(void)
{if(bt1ms) //每1ms进入{bt1ms = 0;if(receTimeOut>0) //接收到数据赋值5,每接收一个数据receTimeOut赋值5{receTimeOut--; //等待5msif(receTimeOut==0 && receCount>0) //判断通讯接收是否超时{EN_485 = 0; //将485置为接收状态 receCount = 0;// //将接收地址偏移寄存器清零} }}
}/************************************************
//fuction:01 读单个或多个线圈状态
//主机发送 地址 + 功能码 + 起始地址(2个字节) + 线圈数量 (2个字节) + 校验码
//从机返回 地址 + 功能码 + 字节数+ 线圈状态 + 校验码
**************************************************/
void readCoils(void) //fuction:01 读单个或多个线圈状态
{unsigned int addr;unsigned int tempAddr;unsigned int byteCount;unsigned int bitCount;unsigned int crcData;unsigned int i,k;unsigned int tempData;unsigned char exit = 0;addr=(receBuf[2]<<8+receBuf[3]);tempAddr = addr; //读取地址bitCount = (receBuf[4]<<8) + receBuf[5]; //读取的位个数byteCount = bitCount / 8; //字节个数if(bitCount%8 != 0) //不能整除加一个字节byteCount++; for(k=0;k<byteCount;k++){sendBuf[k+3]=0;for(i=0;i<8;i++){getCoilVal(tempAddr,&tempData);//一位一位读取sendBuf[k+3] |= tempData<<i;//移位完成一个字节tempAddr++;//地址加1if(tempAddr>=addr+bitCount)//判读是否要读取的位都读好,读好后设定标志位{exit = 1; break; //跳出i语句循环}}if(exit == 1) break ;//跳出k语句循环} sendBuf[0]=LocalAddr; //单片机控制板的地址sendBuf[1]=0x01; //发送功能码sendBuf[2]=byteCount; //发送字节数byteCount+=3; //CRC16校验个数crcData=CRC16_Check(sendBuf,byteCount);//crc16校验sendBuf[byteCount++] = crcData & 0xff; //发送crc16校验低八位校验码sendBuf[byteCount++] = crcData >> 8; //发送crc16校验高八位校验码RS485_Send(sendBuf,byteCount);
}
/************************************************
//fuction:02 读单个或多个线圈状态
//主机发送 地址 + 功能码 + 起始地址(2个字节) + 输入点数量 (2个字节) + 校验码
//从机返回 地址 + 功能码 + 字节数+ 输入点状态 + 校验码
**************************************************/
void readInPutCoils(void) //fuction:02 读取线圈输入(只读寄存器)状态
{unsigned int addr;unsigned int tempAddr;unsigned int byteCount;unsigned int bitCount;unsigned int crcData;unsigned int i,k;unsigned int tempData;unsigned char exit = 0;addr=(receBuf[2]<<8+receBuf[3])+10000;tempAddr = addr; //读取地址bitCount = (receBuf[4]<<8) + receBuf[5]; //读取的位个数byteCount = bitCount / 8; //字节个数if(bitCount%8 != 0)byteCount++; for(k=0;k<byteCount;k++){sendBuf[k+3]=0;for(i=0;i<8;i++){getCoilVal(tempAddr,&tempData);//一位一位读取sendBuf[k+3] |= tempData<<i;//移位完成一个字节tempAddr++;//地址加1if(tempAddr>=addr+bitCount)//判读是否要读取的位都读好,读好后设定标志位{exit = 1; break; //跳出i语句循环}}if(exit == 1) break ;//跳出k语句循环} sendBuf[0]=LocalAddr; //单片机控制板的地址sendBuf[1]=0x02; //发送功能码sendBuf[2]=byteCount; //发送字节数byteCount+=3; //CRC16校验个数 //加上前面的地址,功能码,地址 共3+byteCount个字节crcData=CRC16_Check(sendBuf,byteCount);//crc16校验sendBuf[byteCount++] = crcData & 0xff; //发送crc16校验低八位校验码sendBuf[byteCount++] = crcData >> 8; //发送crc16校验高八位校验码RS485_Send(sendBuf,byteCount);
}
/********function code : 03,读取多个寄存器值 ********/
主机发送 地址 + 功能码 + 起始地址(2个字节) + 寄存器数量 (2个字节) + 校验码
/从机返回 地址 + 功能码 + 字节数+ 寄存器值 (N*2,一个数据2个字节) + 校验码
/*********************************************************/
void readRegisters(void) //function code : 03,读取多个寄存器值
{unsigned int addr;unsigned int tempAddr;unsigned int crcData;unsigned int readCount;unsigned int byteCount;unsigned int i;unsigned int tempData = 0; addr = ((receBuf[2]<<8)+receBuf[3])+40000; //读取初始地址 , //+40000,保持寄存器偏移地址tempAddr = addr;readCount = (receBuf[4]<<8) + receBuf[5]; //要读的个数 ,整型byteCount = readCount * 2; //每个寄存器内容占高,低两个字节for(i=0;i<byteCount;i+=2,tempAddr++){getRegisterVal(tempAddr,&tempData); sendBuf[i+3] = tempData >> 8; sendBuf[i+4] = tempData & 0xff; }sendBuf[0]=LocalAddr; //单片机控制板的地址sendBuf[1]=0x03; //发送功能码sendBuf[2]=byteCount; //发送字节数byteCount+=3; //CRC16校验个数crcData=CRC16_Check(sendBuf,byteCount);//crc16校验sendBuf[byteCount++] = crcData & 0xff; //发送crc16校验低八位校验码sendBuf[byteCount++] = crcData >> 8; //发送crc16校验高八位校验码RS485_Send(sendBuf,byteCount);
}
/*************************************************************
//fuction:05 ,强制单个线圈
//主机发送 地址 + 功能码 + 线圈地址(2个字节) + 写入值(2个字节)(置零:0x0000 ;;置一:0xff00) +校验码
//从机返回 地址 + 功能码 + 线圈地址(2个字节) + 写入值(2个字节)(置零:0x0000 ;;置一:0xff00) +校验码
************************************************************/
void forceSingleCoil(void) //fuction:05 ,强制单个线圈
{unsigned int addr;unsigned int tempAddr;unsigned int tempData = 0;unsigned int ONoff;unsigned char i;addr = (receBuf[2]<<8)+receBuf[3]; //读取初始地址 tempAddr = addr;//读取地址ONoff = (receBuf[4]<<8) + receBuf[5]; if(ONoff==0xff00) tempData = 1;//设为ONelse if(ONoff==0x0000) tempData = 0;//设为OFFsetCoilVal(tempAddr,tempData); for(i=0;i<receCount;i++)sendBuf[i] = receBuf[i];RS485_Send(sendBuf,receCount);
}
/****************fuction:06设置单个寄存器ok**********************************************************/
//主机发送:从机地址 + 功能码 + 寄存器地址(2个字节,先寄存器高位,在寄存器低位)+数据写入值(2个字节,先高位再低位)+ CRC16校验(低位再高位)
//从机返回:从机地址 + 功能码 + 寄存器地址(2个字节,先寄存器高位,在寄存器低位)+数据写入值(2个字节,先高位再低位)+ CRC16校验(低位再高位)
/****************************************************************************************************/
void presetSingleRegister(void) //fuction:06设置单个寄存器
{unsigned int addr;unsigned int tempAddr;unsigned int tempData;unsigned char i;addr = (receBuf[2]<<8)+receBuf[3]; //读取初始地址 tempAddr = addr+40000;//读取地址tempData = (receBuf[4]<<8) + receBuf[5];//设置寄存器写入值setRegisterVal(tempAddr,tempData);for(i=0;i<receCount;i++) //回发,把数据发送回plcsendBuf[i] = receBuf[i];RS485_Send(sendBuf,8);
}
void presetMultipleRegisters(void) //function code : 16,设置多个寄存器值
{unsigned int addr;unsigned int tempAddr;unsigned int crcData;unsigned int tempData;unsigned int byteCount;unsigned char i;addr = (receBuf[2]<<8)+receBuf[3]; //读取初始地址 tempAddr = addr+40000;//读取地址byteCount=receBuf[6];//写入字节个数for(i=0;i<byteCount;i+=2,tempAddr++){tempData = (receBuf[i+7]<<8) + receBuf[i+8];//待设置寄存器值setRegisterVal(tempAddr,tempData); }sendBuf[0] = LocalAddr;sendBuf[1] = 16; //function code : 16sendBuf[2] = addr >> 8; //寄存器地址高位sendBuf[3] = addr & 0xff;//寄存器地址低位sendBuf[4] = byteCount >> 8;//待设置寄存器数量高位sendBuf[5] = byteCount & 0xff;//待设置寄存器数量低位crcData=CRC16_Check(sendBuf,6);//crc16校验sendBuf[6] = crcData & 0xff; //CRC代码低位在前sendBuf[7] = crcData >> 8; //高位在后RS485_Send(sendBuf,8);
}void getCoilVal(unsigned int addr,unsigned int *tempData)//取线圈状态,0或1
{//过压等switch(addr){default :break;}
}
/*******************************读取寄存器内容函数************/
void getRegisterVal(unsigned int addr,unsigned int *tempData) //读取寄存器内容函数*
{switch(addr){case RWDAT0: *tempData=read_num; break; //运行时间sdefault:break;}
}
void setCoilVal(unsigned int addr,unsigned int tempData)//设定单一线圈状态
{switch(addr){default:break;}
}void setRegisterVal(unsigned int addr,unsigned int tempData) //设置寄存器内容函数
{switch(addr){ case RWDAT3: EG_OUTDY(tempData); break; //电压 180-220case RWDAT4: EG_OUTPL(tempData); break; //频率 0:50 1:60case RWDAT5: SetTextValue(0,13,tempData); break; //开机次数default:break;}
}
/*************************查询uart接收的数据包内容函数 **************************/
函数功能:丛机根据串口接收到的数据包receBuf[1]里面的内容,即function code执行相应的命令
/********************************************************************************/
void check_modbus(void)
{unsigned int crcData,tempData,temp;timeProc();//定时处理,数据保留5msif(receCount>4) //如果接收到数据{if(receBuf[0]==LocalAddr) //核对地址{if(receBuf[1]<10){if(receCount>=8) //数据大于8个进入,地址1 功能码1 4 校验码2{crcData = CRC16_Check(receBuf,6); //核对校验码temp = (receBuf[7]<<8)+receBuf[6];if(temp==crcData){switch(receBuf[1]) //读取功能码{case 1: readCoils(); break; //读取线圈输出状态(一个或多个) case 2: readInPutCoils(); break; //读取线圈输入(只读寄存器)状态case 3: readRegisters(); break; //读取多个寄存器值case 5: forceSingleCoil(); break; //强制单个线圈case 6: presetSingleRegister(); break; //设置单个寄存器default:break; }}}} else if(receBuf[1]==16){tempData = (receBuf[4]<<8) + receBuf[5]; //设置寄存器个数tempData = tempData * 2; //数据个数= 寄存器*2tempData += 9; //从询问数据包格式可知,receCount应该等于9+byteCountif(receCount>=tempData){crcData = CRC16_Check(receBuf,tempData-2);if(crcData==((receBuf[tempData-1]<<8)+ receBuf[tempData-2]))if(receBuf[1]==16)presetMultipleRegisters(); receCount=0;} }} }
}
五、项目演示
2022光伏电子单片机部分
这篇关于智能离网微逆变系统的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!