/* * user.c * * Created on: 2023年6月25日 * Author: wyf */ #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,adc_state = 1; //电场极性,投退状态 volatile uint8_t electric_flag = 0; //外加的反向电场极限,0为负,1为正 volatile uint8_t motor_state = 1; //电机状态,0为正常, 1不正常 volatile uint16_t RS485ADDR = 0; //485地址 uint16_t RegularConvData_Tab[ADCBUFF_LEN] = {0};//ADC采集原始数据 volatile int16_t adc_max = 0; //最终峰峰值 volatile int16_t adc_positive = 0, adc_negative=0; //加外加电场后的adc值 volatile int16_t estimate_value = 40; //投退判断的差值 volatile uint16_t pwm_pulse = 0; //pwm波脉宽 volatile int16_t adcValue_factor = 0; //adc测量值的修正系数*10 volatile int16_t adcValue_addnum = 0; //adc测量值的加减系数 volatile uint16_t motor_runtime =0; //电机运行时间 volatile uint16_t bad_runtime = 0; //恶劣环境运行时间 volatile int16_t baud_rate = 0; //波特率;0:9600, 1:19200 2:57600 3: 115200 uint8_t tempe = 0,humidness = 0; //温度湿度 //uint32_t current_addr = FLASHmotor_runtime; //记录当前电机运行时间的地址 int16_t threshold_value = 300; //传感器上限阈值,低于300时,认为是退 int16_t voltage = 0; //电压 int16_t reference =0; //电压参考值 int16_t voltage_thresh = 60; //投退电压阈值 char version_string[]="DCE-2406-V5.5_HAL"; uint16_t version_number = 550; 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}; //寄存器值 void user_init(void) { __HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE); __HAL_UART_CLEAR_IT(&huart1,UART_CLEAR_IDLEF|UART_CLEAR_TCF); bsp_InitTimer(); AHT20_Init(&SENx,2000,0x38); //2000:读取数据周期2S; 0x38:AHT20地址 motor_state =1; } //求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*adcValue_factor/10 + adcValue_addnum; adc1_max = polarity*adc1_max; adc_max = adc1_max; if(electric_flag == 1) { if(adc_max>adc_positive) { adc_positive = adc_max; } } else if(electric_flag == 0) { if(adc_max> 1) ^ 0xA001; // 0xA001 = reverse 0x8005 else crc = (crc >> 1); } } return crc; } //03指令,读取传感器数据 void MODBUS_03H(void) { //接收到的数据帧 //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] = adc_max; user_register[2] = adc_state; if(voltage == 0) user_register[2]= 0; else if(abs(voltage) < voltage_thresh && user_temp>6) { user_register[2]= 0; voltage = 0; } user_register[3] = motor_state; user_register[4] = pwm_pulse; user_register[5] = adcValue_factor; user_register[6] = adcValue_addnum; user_register[7] = motor_runtime; user_register[8] = baud_rate; user_register[9] = (humidness<<8)|tempe; user_register[10] = estimate_value; user_register[11] = threshold_value; user_register[12] = voltage; if(abs(adc_max)>3200) { user_register[12] =200; } user_register[13] = 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); } } uint8_t reference_flag =0; //06指令,设置寄存器 void MODBUS_06H(void) { 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); //计算CRC for(uint8_t i = 0; i<6; i++) { TXBuff[i] = uBuff[i]; } TXBuff[6] = crc&0xff; TXBuff[7] = crc>>8; //修改地址 if(reg == 0x000f && TXBuff[6]== uBuff[6] && TXBuff[7]== uBuff[7]) { if(data>=1 && data <= 247) { uint8_t temp = RS485ADDR; RS485ADDR = data; if(write_flash() == 0) { if(uBuff[1] != 0) { send_ack(8); } } else { RS485ADDR = temp; } } else { TXBuff[4] = 0xFF; TXBuff[5] = 0xFF; crc = crc16_modbus( uBuff,6); //计算CRC TXBuff[6] = crc&0xff; TXBuff[7] = crc>>8; if(uBuff[0] != 0) //广播地址不返回 { send_ack(8); } } } //设置PWM波占空比 else if(reg == 0x0004 && TXBuff[6]== uBuff[6] && TXBuff[7]== uBuff[7]) { if(data>=0 && data<= 1000) //从机地址要大于等于1,小于等于247 { int16_t temp = pwm_pulse; pwm_pulse = data; //更新地址 if(write_flash() == 0) { send_ack(8); __HAL_TIM_SET_COMPARE(&htim14,TIM_CHANNEL_1,pwm_pulse); //设置脉宽 } else { pwm_pulse = temp; } } } //设置传感器缩放系数 else if(reg == 0x0005 && TXBuff[6]== uBuff[6] && TXBuff[7]== uBuff[7]) { if(data>=-3300 && data<= 3300) //数据大于1小于3300 { int16_t temp = adcValue_factor; adcValue_factor = data*10/adc_max; if(data >= 5 && data <= 20)adcValue_factor = data; if(adcValue_factor>=5 && adcValue_factor<=20) { if(write_flash() == 0) { send_ack(8); } else { adcValue_factor = temp; } } } } //设置传感器加减系数 else if(reg == 0x0006 && TXBuff[6]== uBuff[6] && TXBuff[7]== uBuff[7]) { if(data >= -3300 && data <= 3300 && data != 0) { int16_t temp = adcValue_addnum; adcValue_addnum = data; if(write_flash() == 0) { send_ack(8); } else { adcValue_addnum = temp; } } if(data ==0) { send_ack(8); DISABLE_INT(); NVIC_SystemReset(); } } /* //设置电机运行时间 else if(reg == 0x0007 && TXBuff[6]== uBuff[6] && TXBuff[7]== uBuff[7]) { uint16_t temp = motor_runtime; motor_runtime = data; current_addr = 0x080077D8; //在开头的位置写,则会清除整个区域 bad_runtime =0; if(write_runtime() == 0) { send_ack(8); } else { motor_runtime =temp ; } } */ //设置波特率 else if(reg == 0x0008 && TXBuff[6]== uBuff[6] && TXBuff[7]== uBuff[7]) { if(data >= 0 && data <= 3 ) { int16_t temp = baud_rate; baud_rate = data; if(write_flash() == 0) { send_ack(8); Uart_SetBaud(baud_rate); } else { baud_rate = temp; } } } //设置投退方波阈值 else if(reg == 0x000A && TXBuff[6]== uBuff[6] && TXBuff[7]== uBuff[7]) { if(data >= 0 && data <= 1500 ) { int16_t temp = estimate_value; estimate_value = data; if(write_flash() == 0) { send_ack(8); } else { estimate_value = temp; } } } //设置退阈值 else if(reg == 0x000B && TXBuff[6]== uBuff[6] && TXBuff[7]== uBuff[7]) { if(data >= 0 && data <= 1500 ) { int16_t temp = threshold_value; threshold_value = data; if(write_flash() == 0) { send_ack(8); } else { threshold_value = temp; } } } //设置电压参考值 else if(reg == 12 && TXBuff[6]== uBuff[6] && TXBuff[7]== uBuff[7]) { if(data >= -220 && data <= 220 ) { int16_t temp = reference; if(data != 0) { reference = 110.0/data*adc_max; } else { reference =1; } reference_flag = 1; if(write_flash() == 0) { send_ack(8); } else { reference = temp; } } } //设置电压阈值 else if(reg == 13 && TXBuff[6]== uBuff[6] && TXBuff[7]== uBuff[7]) { if(data >= 0 && data <= 220 ) { int16_t temp = voltage_thresh; voltage_thresh = data; if(write_flash() == 0) { send_ack(8); } else { voltage_thresh = temp; } } } } uint8_t writeflash(void) { FLASH_EraseInitTypeDef EraseInitType; uint32_t PageError; uint8_t a[24] = {0}; int16_t reference_temp; //电压标定值 reference_temp = *(int16_t*)(FLASH485_ADDR+14); if(reference_temp == 0x0000 ||reference_temp == -1) { reference_temp = 0; } //stm32g030F4P6: flash 32k,2k一页,共16页 EraseInitType.TypeErase = FLASH_TYPEERASE_PAGES; //页擦页 EraseInitType.Banks =FLASH_BANK_1; EraseInitType.Page = 15; //擦除页地址 EraseInitType.NbPages = 1; //擦除数量 //stm32是小端模式,低位在前 a[0] = RS485ADDR&0xFF; //地址 a[1] = RS485ADDR>>8; a[2] = pwm_pulse&0xFF; //占空比 a[3] = pwm_pulse>>8; a[4] = adcValue_factor&0xFF; //数据修正的比例系数 a[5] = adcValue_factor>>8; a[6] = adcValue_addnum & 0xFF; //加减系数 a[7] = adcValue_addnum >>8; a[8] = baud_rate & 0xFF; //加减系数 a[9] = baud_rate >>8; a[10] = estimate_value & 0xFF; a[11] = estimate_value >>8; a[12] = threshold_value & 0xFF; a[13] = threshold_value >>8; a[14] = reference_temp & 0xFF; a[15] = reference_temp >> 8; if(reference_flag == 1) { a[14] = reference & 0xFF; a[15] = reference >> 8; reference_flag = 0; } a[16] = voltage_thresh & 0xFF; a[17] = voltage_thresh >> 8; HAL_FLASH_Unlock(); //解锁 if(HAL_FLASHEx_Erase(&EraseInitType, &PageError) != HAL_OK) //擦除 { HAL_FLASH_Lock(); return 1; } uint64_t *b = (uint64_t*)a; // uint8_t i = 0; // for(i=0;i++;i<3) // { // if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, FLASH485_ADDR+i*8, *(b+i)) != HAL_OK) // { // HAL_FLASH_Lock(); // return 3 ; // } // } if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, FLASH485_ADDR, *b) != HAL_OK) { HAL_FLASH_Lock(); return 3 ; } if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, FLASH485_ADDR+8, *(b+1) ) != HAL_OK) { HAL_FLASH_Lock(); return 3 ; } if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, FLASH485_ADDR+16, *(b+2) ) != HAL_OK) { HAL_FLASH_Lock(); return 3 ; } HAL_FLASH_Lock(); return 0; } //把参数写到flash中 uint8_t write_flash(void) { uint8_t a =0; DISABLE_INT(); a= writeflash(); ENABLE_INT(); return a; } //取消运行时间功能 /* uint8_t write_runtime(void) { FLASH_EraseInitTypeDef EraseInitType; uint32_t PageError; //stm32g030F4P6: flash 32k,2k一页,共16页 EraseInitType.TypeErase = FLASH_TYPEERASE_PAGES; //页擦页 EraseInitType.Banks =FLASH_BANK_1; EraseInitType.Page = 14; //擦除页地址 EraseInitType.NbPages = 1; //擦除数量 current_addr += 8; HAL_FLASH_Unlock(); if(current_addr > 0x080077D8) { current_addr = FLASHmotor_runtime; //解锁 if(HAL_FLASHEx_Erase(&EraseInitType, &PageError) != HAL_OK) //擦除 { HAL_FLASH_Lock(); return 1; } } uint64_t b = motor_runtime; //<<16 | bad_runtime; if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, current_addr, b) != HAL_OK) { HAL_FLASH_Lock(); return 3 ; } HAL_FLASH_Lock(); return 0; } */ //发送数据,参数:数据长度;数据放在全局变量txbuff中 void send_ack(uint8_t a) { HAL_GPIO_WritePin(TX485_EN_GPIO_Port, TX485_EN_Pin, GPIO_PIN_SET);//使能485芯片发送 HAL_UART_Transmit_DMA(&huart1, TXBuff, a); while(HAL_DMA_GetState(&hdma_usart1_tx) != HAL_DMA_STATE_READY); delay_ms(5); HAL_GPIO_WritePin(TX485_EN_GPIO_Port, TX485_EN_Pin, GPIO_PIN_RESET);//使能485芯片接收 } //外部中断回调函数, 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(motor_state == 1) { bsp_StartAutoTimer(2,500); //led2闪烁 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,last_state=1; if(HAL_GPIO_ReadPin(SDA_GPIO_Port, SDA_Pin) == GPIO_PIN_SET) //上升沿 { electric_flag = 1; motor_runtime = adc_positive - adc_negative; if(adc_positive - adc_negative >estimate_value) { if(adc_positive>0) //电压为正 { posinumber++; neganumber = 0; if(posinumber>=3) { adc_state = 0; //0是退 } } else { //电压为负时,峰峰值计算时,当前的正值减上上次的负值 motor_runtime = adc_positive - last_negative; if(adc_positive-last_negative>estimate_value) { posinumber++; neganumber = 0; if(posinumber>=3) { adc_state = 0; //0是退 } } else { neganumber++; posinumber = 0; if(neganumber>=3) { adc_state = 1; //1是投 if(last_state == 0) { reference =0; } } if(neganumber>250)neganumber = 3; } } if(posinumber>250)posinumber = 3; } else { neganumber++; posinumber = 0; if(neganumber>=2) { adc_state = 1; //1是投 if(last_state == 0) { reference =0; } } if(neganumber>250)neganumber = 3; } last_negative =adc_negative; if(threshold_value>=1 && abs(adc_positive)= 5 ) //每6秒钟调用一次 { if(abs(adc_max-last_adc) < 40 && count >= 30) { reference = adc_max; count =0; } last_count = count; last_adc = adc_max; } } else if(reference == 1) //人为设置电压参考值为0时的处理 { voltage =0; if(abs(adc_max-last_adc)>300 ) { reference = 0; write_flash(); } last_adc = adc_max; } } }