/* * user.c * * Created on: Sep 23, 2024 * Author: 10425 */ #include "user.h" volatile uint8_t usart_count = 0; //串口接收数据个数 uint8_t RxBuff[BUFF_LEN] = {0}; //串口接收缓冲区 uint8_t TXBuff[BUFF_LEN] = {0}; //串口发送缓冲区 uint8_t uBuff[BUFF_LEN] = {0}; //用户缓冲区 volatile int8_t polarity = 1; //电场极性,投退状态 volatile uint8_t electric_flag = 0; //外加的反向电场极限,0为负,1为正 volatile struct REGISTER dev_reg ={0}; uint16_t RegularConvData_Tab[ADCBUFF_LEN] = {0}; //ADC采集原始数据 volatile int16_t adc_positive = 0, adc_negative=0; //加外加电场后的adc值 char version_string[]="DCE-2406-V6.0_HAL"; uint16_t version_number = 600; uint16_t user_temp = 0; /*1:传感器数据 2:投退状态 3:电机状态 * 4:PWM波占空比 5:传感器缩放系数 6:传感器加减系数 * 7:电机运行时间 8:设置波特率 9:温湿度 * 10:方波投退判断阈值 11:传感器退阈值 12:电压值 * 13:电压阈值,电压小于该值时为退 */ int16_t user_register[14] = {0}; //寄存器值 //求adc波形的峰峰值 void ADC_MAX(void) { uint8_t i =0; static uint8_t number = 0; uint16_t max = 0,min = 0; static int16_t adc1_max = 0; max = RegularConvData_Tab[0]; min = RegularConvData_Tab[0]; for(i = 1;i max ) { max = RegularConvData_Tab[i]; } else if(RegularConvData_Tab[i] < min ) { min = RegularConvData_Tab[i]; } } if(max - min > 0) { adc1_max += max - min; } if(number++>=4) { adc1_max = adc1_max/5*3300/4095; adc1_max = adc1_max*dev_reg.adcValue_factor/10 + dev_reg.adcValue_addnum; adc1_max = polarity*adc1_max; // if(humidness>50) // adc1_max += 0.3801*humidness*humidness - 16.825*humidness + 148.37; dev_reg.adc_max = adc1_max; if(electric_flag == 1) { if(dev_reg.adc_max>adc_positive) { adc_positive = dev_reg.adc_max; } } else if(electric_flag == 0) { if(dev_reg.adc_max> 1) ^ 0xA001; // 0xA001 = reverse 0x8005 else crc = (crc >> 1); } } return crc; } void MODBUS_03H() { //接收到的数据帧 //485地址 功能位 寄存器地址 寄存器个数 crc低位 crc高位 uint8_t crch,crcl; uint16_t crcack; uint16_t addr = (uint16_t)uBuff[2]<<8 | uBuff[3]; //寄存器地址 uint16_t number = (uint16_t)uBuff[4]<<8 | uBuff[5]; //寄存器数量 uint16_t crc = crc16_modbus(uBuff,6); //计算CRC crch = crc>>8; crcl = crc&0x00FF; user_register[1] = dev_reg.adc_max; user_register[2] = dev_reg.adc_state; if(dev_reg.voltage == 0) user_register[2]= 0; else if(abs(dev_reg.voltage) < dev_reg.voltage_thresh && user_temp>6) { user_register[2]= 0; dev_reg.voltage = 0; } user_register[3] = dev_reg.motor_state; user_register[4] = dev_reg.pwm_pulse; user_register[5] = dev_reg.adcValue_factor; user_register[6] = dev_reg.adcValue_addnum; user_register[7] = dev_reg.peak_value; user_register[8] = dev_reg.baud_rate; user_register[9] = (dev_reg.humidness<<8)|dev_reg.tempe; user_register[10] = dev_reg.estimate_value; user_register[11] = dev_reg.threshold_value; user_register[12] = dev_reg.voltage; user_register[13] = dev_reg.voltage_thresh; if( (addr+number) <= 14 && crcl == uBuff[6] && crch == uBuff[7]) { uint8_t cnt = 0; TXBuff[cnt++] = uBuff[0]; TXBuff[cnt++] = uBuff[1]; TXBuff[cnt++] = number*2; //数据个数,单位/字节 for(uint8_t i =0;i>8; TXBuff[cnt++] = user_register[addr+i] & 0xFF; } crcack = crc16_modbus(TXBuff,cnt); TXBuff[cnt++] = crcack & 0xff; TXBuff[cnt++] = crcack >>8; send_ack(cnt); } //读取版本号 if(addr == 0x00FF && number == 0x0001 && crcl== uBuff[6] && crch== uBuff[7]) //比较寄存器值和CRC校验值 { uint8_t i; for(i=0;i>8; TXBuff[cnt++] = version_number & 0xFF; crcack = crc16_modbus(TXBuff,cnt); TXBuff[cnt++] = crcack & 0xff; TXBuff[cnt++] = crcack >>8; send_ack(cnt); } } void MODBUS_06H() { enum WRITE_REG_ADDR write_reg_addr; int16_t data = ((int16_t)uBuff[4]<<8)|uBuff[5]; //数据 //要修改的数据 uint16_t reg = ((int16_t)uBuff[2]<<8)|uBuff[3]; //寄存器地址 //寄存器地址 uint16_t crc = crc16_modbus( uBuff,6); for(uint8_t i = 0;i<6;i++) { TXBuff[i] = uBuff[i]; } TXBuff[6] = crc&0xFF; TXBuff[7] = crc>>8; if(TXBuff[6]!=uBuff[6] || TXBuff[7]!=uBuff[7])return; //修改地址 if(reg == 0x000f ) { if(data>=1 && data <= 247) { int16_t temp = dev_reg.addr; dev_reg.addr = data; write_reg_addr = write_addr; if(write_flash(write_reg_addr,data)==HAL_OK) { send_ack(8); } else { dev_reg.addr = temp; } } } //设置PWM波占空比 if(reg == 0x0004) { if(data>=0 && data <= 1000) { int16_t temp = dev_reg.addr; dev_reg.pwm_pulse = data; write_reg_addr = write_pulse; if(write_flash(write_reg_addr,data)==HAL_OK) { send_ack(8); __HAL_TIM_SET_COMPARE(&htim14,TIM_CHANNEL_1,dev_reg.pwm_pulse); //设置脉宽 } else { dev_reg.pwm_pulse = temp; } } } //设置传感器缩放系数 if(reg == 0x0005) { if(data>=-3300 && data <= 3300) { int16_t temp = dev_reg.adcValue_factor; dev_reg.adcValue_factor = data*10/dev_reg.adc_max; if(data>=5 && data <= 20)dev_reg.adcValue_factor = data; write_reg_addr = write_factor; if(dev_reg.adcValue_factor>=5 && dev_reg.adcValue_factor<=20) { if(write_flash(write_reg_addr,data)==HAL_OK) { send_ack(8); } else { dev_reg.adcValue_factor = temp; } } } } //设置传感器加减系数 if(reg == 0x0006) { if(data>= -2000 && data <= 2000) { int16_t temp = dev_reg.adcValue_addnum; dev_reg.adcValue_addnum = data; write_reg_addr = write_addnum; if(write_flash(write_reg_addr,data)==HAL_OK) { send_ack(8); } else { dev_reg.adcValue_addnum = temp; } } } //设置波特率 if(reg == 0x0008) { if(data>= 0 && data <= 3) { int16_t temp = dev_reg.baud_rate; dev_reg.baud_rate = data; write_reg_addr = write_baud; if(write_flash(write_reg_addr,data)==HAL_OK) { send_ack(8); } else { dev_reg.baud_rate = temp; } } } //设置投退方波阈值 if(reg == 0x000A) { if(data>= 0 && data <= 1500) { int16_t temp = dev_reg.estimate_value; dev_reg.estimate_value = data; write_reg_addr = write_estimate; if(write_flash(write_reg_addr,data)==HAL_OK) { send_ack(8); } else { dev_reg.estimate_value = temp; } } } //设置原始数据退阈值 if(reg == 0x000B) { if(data>= 0 && data <= 1500) { int16_t temp = dev_reg.threshold_value; dev_reg.threshold_value = data; write_reg_addr = write_threshold; if(write_flash(write_reg_addr,data)==HAL_OK) { send_ack(8); } else { dev_reg.threshold_value = temp; } } } //设置电压参考值 if(reg == 12) { if(data>= -220 && data <= 220) { int16_t temp = dev_reg.reference; if(data != 0) { dev_reg.reference = 110.0/data*dev_reg.adc_max; } else { dev_reg.reference =1; } write_reg_addr = write_reference; if(write_flash(write_reg_addr,dev_reg.reference)==HAL_OK) { send_ack(8); } else { dev_reg.threshold_value = temp; } } } //设置电压阈值 if(reg == 13) { if(data>= 0 && data <= 220) { int16_t temp = dev_reg.voltage_thresh; dev_reg.voltage_thresh = data; write_reg_addr = write_voltageth; if(write_flash(write_reg_addr,data)==HAL_OK) { send_ack(8); } else { dev_reg.voltage_thresh = temp; } } } } void MODBUS_10H() { //用于更新代码,每次固定接收128字节数据 static uint16_t current_addr =1; //当前寄存器地址,表示当前的块号 static uint16_t file_size; //文件大小 static uint16_t current_size = 0; uint16_t crctemp; uint16_t reg_addr = (uint16_t)uBuff[2]<<8 | uBuff[3]; //寄存器地址 uint16_t reg_number = (uint16_t)uBuff[4]<<8 | uBuff[5]; //寄存器数量 uint8_t byte_number = uBuff[6]; //字节数 uint16_t crc = crc16_modbus( uBuff,7+byte_number); if((crc&0xFF)!=uBuff[6+byte_number+1] || crc>>8!=uBuff[6+byte_number+2] || (reg_addr>current_addr&®_addr!=0xFFFF)) { //返回错误响应 if(uBuff[0]!=0) //地址不为0时 { TXBuff[0] = dev_reg.addr; TXBuff[1] = 0x10; TXBuff[2] = 1; //错误码 crctemp = crc16_modbus(TXBuff, 3); TXBuff[3] = crctemp&0xFF; TXBuff[4] = crctemp>>8; send_ack(5); } return; } uint8_t data[128]; memcpy(data,&uBuff[7],128); //起始段 if(reg_addr == 0 && reg_number == 1 && byte_number == 2) { // bsp_StartAutoTimer(8, 100); //升级程序时,灯变为快闪 file_size =0; current_addr = 0; file_size = data[0]<<8 | data[1]; current_addr++; } //数据段 else if(reg_addr == current_addr && reg_number==64 && byte_number == 128) { if(write_code(app2_addr+current_size,data,128) != HAL_OK) { //返回错误响应 if(uBuff[0]!=0) //地址不为0时 { TXBuff[0] = dev_reg.addr; TXBuff[1] = 0x10; TXBuff[2] = 1; //错误码 crctemp = crc16_modbus(TXBuff, 3); TXBuff[3] = crctemp&0xFF; TXBuff[4] = crctemp>>8; send_ack(5); } return; } current_size+= 128; current_addr++; } //结束段 else if (reg_addr == 0xFFFF && reg_number == 1 && byte_number == 2) { if(((data[0]<<8|data[1]) == current_addr) && current_size >= file_size) { //正常响应 if(uBuff[0]!=0) //地址不为0时 { TXBuff[0] = dev_reg.addr; TXBuff[1] = 0x10; TXBuff[2] = reg_addr>>8; //错误码 TXBuff[3] = reg_addr&0xFF; TXBuff[4] = reg_number>>8; //错误码 TXBuff[5] = reg_number&0xFF; crctemp = crc16_modbus(TXBuff, 3); TXBuff[6] = crctemp&0xFF; TXBuff[7] = crctemp>>8; send_ack(8); } //跳转 if(( ( *(volatile uint32_t*)app2_addr)&0x2FFE0000 )==0x20000000) { // uint8_t aa[2] = {0,0}; // AT24C16_WriteBytes(FILE_SIZE_ADDR, aa, sizeof(aa)); // AT24C16_ReadBytes(FILE_SIZE_ADDR, aa, sizeof(aa)); // 禁用中断 HAL_ADC_Stop_DMA(&hadc1); __disable_irq(); SCB->VTOR = app2_addr; LoadApp loadapp; loadapp=(LoadApp)( *(volatile uint32_t*)(app2_addr+4) ); //用户代码区第二个字为程序开始地址(复位地址) __set_MSP(*(volatile uint32_t*)app2_addr); //初始化MSP loadapp(); } } else { // bsp_StartAutoTimer(8, 500); //升级程序时,灯变为快闪 file_size =0; current_addr = 0; } } //正常响应 if(uBuff[0]!=0) //地址不为0时 { TXBuff[0] = dev_reg.addr; TXBuff[1] = 0x10; TXBuff[2] = reg_addr>>8; //寄存器地址 TXBuff[3] = reg_addr&0xFF; TXBuff[4] = reg_number>>8; TXBuff[5] = reg_number&0xFF; //寄存器个数 crctemp = crc16_modbus(TXBuff, 6); TXBuff[6] = crctemp&0xFF; TXBuff[7] = crctemp>>8; send_ack(8); } } //写入代码,length长度必须为8的倍数, HAL_StatusTypeDef write_code(uint32_t addr,uint8_t* data,uint16_t length) { FLASH_EraseInitTypeDef EraseInitType; uint32_t PageError; uint32_t current_page = (addr-FLASH_BASE_ADDR)/FLASH_SECTOR_SIZE; HAL_FLASH_Unlock(); if( (addr-FLASH_BASE_ADDR)%FLASH_SECTOR_SIZE == 0) { EraseInitType.TypeErase = FLASH_TYPEERASE_PAGES; //页擦书 EraseInitType.Page = current_page; //擦除起始页 EraseInitType.NbPages = 1; //擦除数量 if(HAL_FLASHEx_Erase(&EraseInitType, &PageError)!= HAL_OK) { return HAL_ERROR; } } uint64_t *a = (uint64_t*)data; for(int i=0;i>8; temp[1] = data&0xFF; addr = addr+1; return AT24C16_WriteBytes(addr, temp, sizeof(temp)); } //外部中断回调函数, void HAL_GPIO_EXTI_Rising_Callback(uint16_t GPIO_Pin) { static uint8_t count = 0,polaNumber =0; static int16_t last_negative = 0; static GPIO_PinState PH2_value =GPIO_PIN_RESET,PH1_value = GPIO_PIN_RESET; PH2_value = HAL_GPIO_ReadPin(PH2_GPIO_Port, PH2_Pin); PH1_value = HAL_GPIO_ReadPin(PH1_GPIO_Port, PH1_Pin); if(GPIO_Pin == PH1_Pin && PH1_value == GPIO_PIN_SET ) { //判断电机运动状态 static uint32_t last_tick = 0; // last_tick = HAL_GetTick(); uint32_t a = HAL_GetTick(); if( (a -last_tick) < 8) { bsp_StartAutoTimer(4,1000); //1秒没有检测到上升沿,说明电机不正常或红外线发射接收不正常 if(dev_reg.motor_state == 1) { bsp_StartAutoTimer(2,500); //led2闪烁 dev_reg.motor_state = 0; } } last_tick = a; //判断极性 if(PH2_value==GPIO_PIN_SET) { polaNumber ++; } count++; if(count>=10) { if(polaNumber>=3)polarity=1; else {polarity = -1;} count =0; polaNumber =0; } } else if(GPIO_Pin == SDA_Pin) //判断压板投退状态 { bsp_StartAutoTimer(3,5000); //5秒没有上升下降沿,说明可能没有加反向电场 static uint8_t posinumber =0,neganumber = 0; if(HAL_GPIO_ReadPin(SDA_GPIO_Port, SDA_Pin) == GPIO_PIN_SET) //上升沿 { electric_flag = 1; dev_reg.peak_value = adc_positive - adc_negative; if(adc_positive - adc_negative >dev_reg.estimate_value) { if(adc_positive>0) //电压为正 { posinumber++; neganumber = 0; if(posinumber>=3) { dev_reg.adc_state = 0; //0是退 } } else { //电压为负时,峰峰值计算时,当前的正值减上上次的负值 dev_reg.peak_value = adc_positive - last_negative; if(adc_positive-last_negative>dev_reg.estimate_value) { posinumber++; neganumber = 0; if(posinumber>=3) { dev_reg.adc_state = 0; //0是退 } } else { neganumber++; posinumber = 0; if(neganumber>=3) { dev_reg.adc_state = 1; //1是投 } if(neganumber>250)neganumber = 3; } } if(posinumber>250)posinumber = 3; } else { neganumber++; posinumber = 0; if(neganumber>=2) { dev_reg.adc_state = 1; //1是投 } if(neganumber>250)neganumber = 3; } last_negative =adc_negative; if(dev_reg.threshold_value>=10 && abs(adc_positive)= 5 ) //每6秒钟调用一次 { if(abs(dev_reg.adc_max-last_adc) < 30 && count >= 30) { dev_reg.reference = dev_reg.adc_max; count =0; } last_count = count; last_adc = dev_reg.adc_max; } } else if(dev_reg.reference == 1) //人为设置电压参考值为0时的处理 { dev_reg.voltage =0; if(abs(dev_reg.adc_max-last_adc)>300 ) { dev_reg.reference = 0; write_flash(write_reference,dev_reg.reference); } last_adc = dev_reg.adc_max; } } }