110VCGQ/project/daqidianchang/Core/Src/user.c
2024-11-18 10:09:39 +08:00

375 lines
8.2 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* user.c
*
* Created on: 2023年8月3日
* 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;
}
}
}