基于TOPWAY液晶屏的水质检测仪设计
四、软件设计
本文引用地址://m.amcfsurvey.com/article/202204/433019.htm1、LCD驱动编写
根据协议内容,编写写16位数字变量的驱动
/**
briefLCD发送16位变量
param adr:变量地址
param dt:发送的变量
return 无
*/
voidlcd_send_pv16(uint32_tadr,uint16_tdt)
{
uint8_tsend_buf[32];
uint8_tidx=0;
send_buf[idx++] =0xaa;
send_buf[idx++] =0x3d;
adr=ntohl(adr);//大小端转换
memcpy((uint8_t*)&send_buf[idx], (uint8_t*)&adr,sizeof(uint32_t));
idx+=sizeof(uint32_t);
dt=ntohs(dt);//大小端转换
memcpy((uint8_t*)&send_buf[idx], (uint8_t*)&dt,2);
idx+=2;
send_buf[idx++] =0xcc;
send_buf[idx++] =0x33;
send_buf[idx++] =0xc3;
send_buf[idx++] =0x3c;
send_data1(send_buf,idx);
}
LCD左推进写曲线数据
/**
brief LCD左推进写曲线数据
param adr:变量地址
param adr_curve:插入位置
param dt:发送的变量
return 无
*/
voidlcd_send_curve(uint32_tadr,uint16_tadr_curve,uint16_tdt)
{
uint8_tsend_buf[64];
uint8_tidx=0;
send_buf[idx++] =0xaa;
send_buf[idx++] =0x4e;
adr=ntohl(adr);
memcpy((uint8_t*)&send_buf[idx], (uint8_t*)&adr,sizeof(uint32_t));
idx+=sizeof(uint32_t);
adr_curve=ntohs(adr_curve);
memcpy((uint8_t*)&send_buf[idx], (uint8_t*)&adr_curve,sizeof(uint16_t));
idx+=sizeof(uint16_t);
dt=ntohs(dt);
memcpy((uint8_t*)&send_buf[idx], (uint8_t*)&dt,sizeof(uint16_t));
idx+=sizeof(uint16_t);
send_buf[idx++] =0xcc;
send_buf[idx++] =0x33;
send_buf[idx++] =0xc3;
send_buf[idx++] =0x3c;
send_data1(send_buf,idx);
}
跳转页面的驱动
/**
brief LCD跳转页面
param page:页面地址
return 无
*/
voidlcd_send_page(uint16_tpage)
{
uint8_tsend_buf[64];
uint8_tidx=0;
send_buf[idx++] =0xaa;
send_buf[idx++] =0x70;
page=ntohs(page);
memcpy((uint8_t*)&send_buf[idx], (uint8_t*)&page,sizeof(uint16_t));
idx+=sizeof(uint16_t);
send_buf[idx++] =0xcc;
send_buf[idx++] =0x33;
send_buf[idx++] =0xc3;
send_buf[idx++] =0x3c;
send_data1(send_buf,idx);
}
设置时间的驱动
/**
brief LCD设置时间
param page 无
return 无
*/
voidlcd_send_time(void)
{
uint8_tsend_buf[64];
uint8_tidx=0;
send_buf[idx++] =0xaa;
send_buf[idx++] =0x9c;
memcpy((uint8_t*)&send_buf[idx], (uint8_t*)&my_rtc,sizeof(MYRTC));
idx+=sizeof(MYRTC);
send_buf[idx++] =0xcc;
send_buf[idx++] =0x33;
send_buf[idx++] =0xc3;
send_buf[idx++] =0x3c;
send_data1(send_buf,idx);
}
读取时间的驱动
/**
brief LCD读取时间
param page 无
return 无
*/
voidlcd_read_time(void)
{
uint8_tsend_buf[64];
uint8_tidx=0;
send_buf[idx++] =0xaa;
send_buf[idx++] =0x9b;
send_buf[idx++] =0xcc;
send_buf[idx++] =0x33;
send_buf[idx++] =0xc3;
send_buf[idx++] =0x3c;
send_data1(send_buf,idx);
}
接收LCD数据的程序
voidlcd_pro(void)
{
staticuint32_ttimer_lcd=0;
if(timer6-timer_lcd<9)
return;
timer_lcd=timer6;
if(lcd_rx.len<5)
return;
if(lcd_rx.rx_buff[0] !=0xaa)
{
memset((uint8_t*)&lcd_rx.rx_buff,0,lcd_rx.len);
lcd_rx.len=0;
return;
}
else
{
switch(lcd_rx.rx_buff[1])
{
case0x79://触摸
lcd.page=lcd_rx.rx_buff[3];
lcd.touch_id=lcd_rx.rx_buff[4];
break;
case0x77://下发数据
if(lcd_rx.rx_buff[3] ==0x08)
{
if(lcd_rx.rx_buff[5] ==0x0A)//年
{
my_rtc.year=lcd_rx.rx_buff[7];
}
elseif(lcd_rx.rx_buff[5] ==0x0C)//月
{
my_rtc.month=lcd_rx.rx_buff[7];
}
elseif(lcd_rx.rx_buff[5] ==0x0E)//日
{
my_rtc.day=lcd_rx.rx_buff[7];
}
elseif(lcd_rx.rx_buff[5] ==0x10)//时
{
my_rtc.hour=lcd_rx.rx_buff[7];
}
elseif(lcd_rx.rx_buff[5] ==0x12)//分
{
my_rtc.min=lcd_rx.rx_buff[7];
}
elseif(lcd_rx.rx_buff[5] ==0x14)//秒
{
my_rtc.sec=lcd_rx.rx_buff[7];
}
lcd_send_time();
}
break;
case0x9B://读取时间
memcpy((uint8_t*)&my_rtc, (uint8_t*)&lcd_rx.rx_buff[2],sizeof(MYRTC));
break;
default:
break;
}
memset((uint8_t*)&lcd_rx.rx_buff,0,lcd_rx.len);
lcd_rx.len=0;
}
}
2、PH值采集
这里用的传感器是模拟信号,可以直接使用单片机的AD去采集值,转化为电压之后,根据拟合后的公式直接转换为PH值,程序如下
voidph_pro(void)
{
staticuint32_ttimer_ph=0;
uint16_tadc_value=0;
floatvol=0.0;
if(timer6-timer_ph>PH_COLLECT_TIME)
{
HAL_ADC_Start(&hadc1);//启动ADC单次转换
HAL_ADC_PollForConversion(&hadc1,50);//等待ADC转换完成
if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1),HAL_ADC_STATE_REG_EOC))
{
adc_value=HAL_ADC_GetValue(&hadc1);//读取ADC转换数据
vol= ((double)adc_value/4096)*3.3*2;//转化为实际电压值
printf("sensor log:adc_value =%d, vol =%.2fV.n",adc_value,vol);
ph_buf[FILTER_N] = (uint16_t)((5.9647*vol+22.255)*10);//转换为PH值
for(i =0; i <FILTER_N; i++)
{
ph_buf[i] =ph_buf[i +1];// 所有数据左移,低位仍掉
}
pv.ph=MedianFilter(ph_buf,FILTER_N);//中值平均滤波
printf("sensor log:ph%drn",pv.ph);
}
lcd_send_pv16(0x080000,pv.ph);//给LCD发送数据
lcd_send_curve(0x060000,224,pv.ph);//给LCD左推进发送曲线
timer_ph+=PH_COLLECT_TIME;
}
}
3、池水温度值采集
使用的是经典的DS18B20,单总线获取温度,程序如下
voidds18b20_pro(void)
{
uint16_ti=0;
staticuint32_ttimer_ds18b20=0;
if(timer6-timer_ds18b20>DS_COLLECT_TIME)
{
te_buf[FILTER_N] =DS18B20_Get_Temp();
for(i=0;i<FILTER_N;i++)
{
te_buf[i] =te_buf[i+1];// 所有数据左移,低位仍掉
}
pv.te=MedianFilter(te_buf,FILTER_N);//中值平均滤波
lcd_send_pv16(0x080002,pv.te);//给LCD发送数据
lcd_send_curve(0x0600e0,224,pv.te+100);//给LCD左推进发送曲线
printf("sensor log:te%drn",pv.te);
timer_ds18b20+=DS_COLLECT_TIME;
}
}
4、环境温湿度值采集
使用的是国产的AHT10,IIC协议获取温湿度,程序如下
voidaht_pro(void)
{
uint16_ti=0;
staticuint32_ttimer_aht=0;
if(timer6-timer_aht>AHT_COLLECT_TIME)
{
AHT10ReadData(&tem_buf[FILTER_N], &hum_buf[FILTER_N]);
for(i=0;i<FILTER_N;i++)
{
hum_buf[i] =hum_buf[i+1];// 所有数据左移,低位仍掉
tem_buf[i] =tem_buf[i+1];// 所有数据左移,低位仍掉
}
pv.tem=MedianFilter(tem_buf,FILTER_N);//中值平均滤波
pv.hum=MedianFilter(hum_buf,FILTER_N);//中值平均滤波
printf("sensor log:tem%drn",pv.tem);
printf("sensor log:hum%drn",pv.hum);
lcd_send_curve(0x0602a0,224,pv.tem+100);//给LCD左推进发送曲线
lcd_send_curve(0x0601c0,224,pv.hum);//给LCD左推进发送曲线
lcd_send_pv16(0x080004,pv.hum);//给LCD发送数据
lcd_send_pv16(0x080006,pv.tem);//给LCD发送数据
timer_aht+=AHT_COLLECT_TIME;
}
}
5、LCE操作流程图
五、展示
主界面
水质曲线界面
环境温湿度曲线界面
效果杠杠的,大屏高分辨率,操作简单高效,真是一次完美的开发体验!!!
评论