110VCGQ/project/daqidianchang/Core/Src/user.c

375 lines
8.2 KiB
C
Raw Normal View History

2024-11-18 10:09:39 +08:00
/*
* user.c
*
* Created on: 202383
* 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; //电场极性
volatile uint8_t motor_state = 1; //电机状态,1为正常, 0不正常
volatile uint16_t RS485ADDR = 0; //485地址
uint16_t RegularConvData_Tab[ADCBUFF_LEN] = {0}; //ADC采集原始数据
volatile int16_t adc_max = 0; //最终峰峰值
volatile uint16_t pwm_pulse = 0; //pwm波脉宽
volatile uint16_t motor_runtime =0; //电机运行时间
uint8_t tempe = 0,humidness = 0; //温度湿度
uint16_t airpress = 0; //气压计
/*1:传感器数据 2:投退状态 3电机状态
* 4PWM波占空比 5 6
* 7 8: 9:
*/
int16_t user_register[10] = {0}; //寄存器值
void user_init(void)
{
bsp_InitTimer();
__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);
__HAL_UART_CLEAR_IT(&huart1,UART_CLEAR_IDLEF|UART_CLEAR_TCF);
}
//求adc波形的峰峰值
void ADC_MAX(void)
{
uint8_t i =0;
static uint8_t number = 0;
uint16_t max = 0,min = 0;
static int32_t adc1_max = 0;
max = RegularConvData_Tab[0];
min = RegularConvData_Tab[0];
for(i = 1;i<ADCBUFF_LEN;i++)
{
if(RegularConvData_Tab[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++>=24)
{
adc1_max = adc1_max/25*3300/4095;
adc_max = polarity*adc1_max;
adc1_max = 0;
number = 0;
}
}
//处理请求
void Usart_Receive(void)
{
if( (uint16_t)uBuff[0] == RS485ADDR && usart_count == 8)
{
switch(uBuff[1])
{
case 0x03: //读传感器数据
MODBUS_03H();
break;
case 0x06:
MODBUS_06H();
break;
default:break;
}
}
else if((uint16_t)uBuff[0] == 0 && usart_count== 8)
{
switch(uBuff[1])
{
case 0x06:
MODBUS_06H();
break;
default:break;
}
}
}
/************************************************************
* Name: CRC-16/MODBUS x16+x15+x2+1
* Poly: 0x8005
* Init: 0xFFFF
* Refin: True
* Refout: True
* Xorout: 0x0000
* Note:
**********************************************************/
uint16_t crc16_modbus(uint8_t *data, uint16_t length)
{
uint8_t i;
uint16_t crc = 0xffff; // Initial value
while(length--)
{
crc ^= *data++; // crc ^= *data; data++;
for (i = 0; i < 8; ++i)
{
if (crc & 1)
crc = (crc >> 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] = motor_state;
// 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;
if( (addr+number) <= 3 && 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<number;i++)
{
TXBuff[cnt++] = user_register[addr+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校验值
{
char string[]="DCE-2302-V5.0_HAL";
uint8_t i;
for(i=0;i<strlen(string);i++)
{
TXBuff[i] = string[i];
}
send_ack(strlen(string)); //打印版本号
}
}
//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 //计算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;
}
}
}
}
uint8_t writeflash(void)
{
FLASH_EraseInitTypeDef EraseInitType;
uint32_t PageError;
uint8_t a[8] = {0};
//stm32g030F4P6: flash 32k,2k一页共16页
EraseInitType.TypeErase = FLASH_TYPEERASE_PAGES; //页擦页
EraseInitType.PageAddress = FLASH485_ADDR; //擦除页地址
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; //加减系数
HAL_FLASH_Unlock(); //解锁
if(HAL_FLASHEx_Erase(&EraseInitType, &PageError) != HAL_OK) //擦除
{
HAL_FLASH_Lock();
return 1;
}
uint64_t *b = (uint64_t*)a;
if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, FLASH485_ADDR, *b) != 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;
}
//发送数据参数数据长度数据放在全局变量txbuff中
void send_ack(uint8_t a)
{
HAL_GPIO_WritePin(TX485_PN_GPIO_Port, TX485_PN_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_PN_GPIO_Port, TX485_PN_Pin, GPIO_PIN_RESET);//使能485芯片接收
}
//外部中断回调函数,
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == PH1_Pin)
{
//判断电机运动状态
static uint32_t last_tick = 0;
uint32_t a = HAL_GetTick();
if( (a -last_tick) < 10)
{
bsp_StartAutoTimer(4,1000); //1秒没有检测到上升沿说明电机不正常或红外线发射接收不正常
if(motor_state == 1)
{
bsp_StartAutoTimer(2,500); //led2闪烁
motor_state = 0;
}
}
last_tick = a;
//判断极性
GPIO_PinState PH2_value = HAL_GPIO_ReadPin(PH2_GPIO_Port, PH2_Pin);
static uint8_t count = 0,polaNumber =0;
if(PH2_value==GPIO_PIN_SET)
{
polaNumber ++;
}
count++;
if(count>5)
{
if(polaNumber>=3)polarity=-1;
else
{polarity = 1;}
count =0;
polaNumber =0;
}
}
}