1) 编写LCD 驱动程序
根据协议内容,编写16位数字变量的动
/**
brief LCD发送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 = ph_buf[i + 1]; // 所有数据左移,低位仍掉
}
pv.ph = MedianFilter(ph_buf, FILTER_N); //中值平均滤波
printf("sensor log:ph %d\r\n", 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 = 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 %d\r\n", 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 = hum_buf[i + 1]; // 所有数据左移,低位仍掉
tem_buf = tem_buf[i + 1]; // 所有数据左移,低位仍掉
}
pv.tem = MedianFilter(tem_buf, FILTER_N); //中值平均滤波
pv.hum = MedianFilter(hum_buf, FILTER_N); //中值平均滤波
printf("sensor log:tem %d\r\n", pv.tem);
printf("sensor log:hum %d\r\n", 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) LCD操作流程图