串口发送数据会修改显示数组的值:原因暂未找到!!!
一、题目
二、分析
题目要求做一个液位检测告警系统,这里将将题目分为四大部分显示界面,设置界面,串口收发,LED灯指示
1.界面
由于题目用到了按键切换不同的界面,所以先做界面与按键切换这一部分。
界面的控制用变量lcd_ctrl控制:若变量等于0x00则表示显示界面;若变量为0x1_,则为设置界面,并且0x10设置阈值1,0x11设置阈值2,0x12设置阈值3
if(unKey_Down == 1) // 界面切换
{
if(lcd_ctrl == 0x00)
{
LCD_Clear(White);
lcd_ctrl = 0x10;
}
else
{
LCD_Clear(White);lcd_ctrl = 0x00;
LCD_Clear(White);lcd_ctrl = 0x00;
iic_24c02_write(high_level_ctrl, 0, 3); //写
high_level_ctrl[0] = high_level_disp[0]; //将显示值(进行加减)赋给控制值
high_level_ctrl[1] = high_level_disp[1];
high_level_ctrl[2] = high_level_disp[2];
}
}
if(unKey_Down == 2 && lcd_ctrl>>4 ==0x1) // 选择,默认第一行:0x10
{
if(lcd_ctrl>= 0x12) lcd_ctrl = 0x10;
else lcd_ctrl++;
}
软件滤波:采用中值滤波,即在在采集ADC数据时,总共采取10次,结果求起平均值即可。
//中值滤波
for(count=0;count<=9;count++)
{
v37_sum += getADC2();
}
v37 = v37_sum* 3.3 / 4096 /10;
v37_sum =0; //清0为下一次准备
high = 100/3.3*v37;
注意:在for循环里面,只将收集到的初次数据相加处理即可,数据转换(乘除)放在循环外面处理,不然每一次都做数据转换浪费内存与计算,这样每一只要进行一次转换即可
在设置阈值进行加减时,要注意各个阈值之间的大小问题,并且设置时文字要高亮显示,使用设置字体颜色函数LCD_SetTextColor(),该函数只对后面的显示文字有效
//lcd显示函数
void Lcd_Proc(void)
{
if((uwTick - uwTick_Lcd_Set_Point)<50) return;//减速函数
uwTick_Lcd_Set_Point = uwTick;
if(lcd_ctrl == 0x00)
{
LCD_SetTextColor(Blue);
sprintf((char *)Lcd_Disp_String, " Liquid Level ");
LCD_DisplayStringLine(Line2, Lcd_Disp_String);
sprintf((char *)Lcd_Disp_String, " Height: %d",(uint8_t)high);
LCD_DisplayStringLine(Line4, Lcd_Disp_String);
sprintf((char *)Lcd_Disp_String, " ADC: %.2f",v37);
LCD_DisplayStringLine(Line6, Lcd_Disp_String);
sprintf((char *)Lcd_Disp_String, " Level: %d",level);
LCD_DisplayStringLine(Line8, Lcd_Disp_String);
}
else
{
LCD_SetTextColor(Blue);
sprintf((char *)Lcd_Disp_String, " Parameter Setup ");
LCD_DisplayStringLine(Line2, Lcd_Disp_String);
if(lcd_ctrl == 0x10){LCD_SetTextColor(Green);} //颜色选择,仅对后面的有效
else{LCD_SetTextColor(Blue); }
sprintf((char *)Lcd_Disp_String, " Threshold 1: %2dcm",high_level_disp[0]);
LCD_DisplayStringLine(Line4, Lcd_Disp_String);
if(lcd_ctrl == 0x11){LCD_SetTextColor(Green);}
else LCD_SetTextColor(Blue);
sprintf((char *)Lcd_Disp_String, " Threshold 2: %2dcm",high_level_disp[1]);
LCD_DisplayStringLine(Line6, Lcd_Disp_String);
if(lcd_ctrl == 0x12){LCD_SetTextColor(Green);}
else LCD_SetTextColor(Blue);
sprintf((char *)Lcd_Disp_String, " Threshold 3: %2dcm",high_level_disp[2]);
LCD_DisplayStringLine(Line8, Lcd_Disp_String);
}
}
// 按键设置
if(unKey_Down == 3) // 加 ,有大小
{
if(lcd_ctrl == 0x10)
{
if(high_level_disp[0]>=95) high_level_disp[0] = 95;
else if(high_level_disp[0]<high_level_disp[1]-5)high_level_disp[0] += 5;
}
if(lcd_ctrl == 0x11)
{
if(high_level_disp[1]>=95) high_level_disp[1] = 95;
else if(high_level_disp[1] <high_level_disp[2]-5 && high_level_disp[1] >high_level_disp[0] )
high_level_disp[1] += 5;
}
if(lcd_ctrl == 0x12)
{
if(high_level_disp[2]>=95) high_level_disp[2] = 95;
else if(high_level_disp[2]>high_level_disp[1])high_level_disp[2] += 5;
}
}
if(unKey_Down == 4) // 减
{
if(lcd_ctrl == 0x10)
{
if(high_level_disp[0]<=5) high_level_disp[0] = 5;
else if(high_level_disp[0]<=high_level_disp[1]-5)high_level_disp[0] -= 5;
}
if(lcd_ctrl == 0x11)
{
if(high_level_disp[1]<=5) high_level_disp[1] = 5;
else if(high_level_disp[1] <high_level_disp[2] && high_level_disp[1] -5>high_level_disp[0] ) high_level_disp[1] -= 5;
}
if(lcd_ctrl == 0x12)
{
if(high_level_disp[2]<=5) high_level_disp[2] = 5;
else if(high_level_disp[2]>high_level_disp[1]+5)high_level_disp[2] -= 5;
}
}
这里将阈值用两个数组来存储,一个用来显示(加减),一个用来控制(真正起作用)。文字高亮显示:在显示前判断一下是否选择这一行,若是设置新的文字颜色;若不是设置文本颜色。有可能会影响显示界面或者第一行,若影响到了直接在它前面加一句颜色的设置函数即可。
2.串口收发
//串口接收中断回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(rx_buffer == 'C')
{
led3 =1;
sprintf((char *)tx_buffer, "C:H%3d+L%d\r\n",(int)high,level);
HAL_UART_Transmit(&huart1,(unsigned char *)tx_buffer, strlen(tx_buffer), 50);
}
if(rx_buffer == 'S')
{
led3 =1;
//sprintf((char *)tx_buffer, "S:TL%2d+TM%2d+TH%2d\r\n",(uint_8)high_level_ctrl[0],(uint_8)high_level_ctrl[1],(uint_8)high_level_ctrl[2]);
sprintf((char *)tx_buffer, "S:TL%2d+TM%2d+TH%2d\r\n",high_level_ctrl[0],high_level_ctrl[1],high_level_ctrl[2]);
HAL_UART_Transmit(&huart1,(unsigned char *)tx_buffer, strlen(tx_buffer), 50);
}
HAL_UART_Receive_IT(&huart1, (uint8_t *)(&rx_buffer), 1);
}
if(high <= high_level_ctrl[0]) level = 0;
else if(high>high_level_ctrl[0] && high<=high_level_ctrl[1]) level = 1;
else if(high>high_level_ctrl[1] && high<=high_level_ctrl[2]) level = 2;
else level = 3;
cur_level = level;
if(cur_level > old_level)
{
led2 = 1;
sprintf(tx_buffer, "A:H%3d+L%1d+U\r\n",(unsigned int)high,(unsigned int)level);
HAL_UART_Transmit(&huart1,(unsigned char *)tx_buffer, strlen(tx_buffer), 50);
}
else if(cur_level < old_level)
{
led2 =1;
sprintf(tx_buffer, "A:H%3d+L%1d+D\r\n",(unsigned int)high,(unsigned int)level);
HAL_UART_Transmit(&huart1,(unsigned char *)tx_buffer, strlen(tx_buffer), 50);
}
old_level = cur_level;
在收到字符,就向串口发送相应的信息,直接在接收中断里面完成即可。判断当前数据是否发送变化: 用三个变量cur_level, old_level, level ;然后比较old与cur即可
3.LED
LED1以1s的周期闪烁,LED2,3在相应的条件下闪烁5次
这里定时精度不是要求的很高,所以直接使用了滴答定时器的uwTick计时。
灯闪烁:即相应的为不断的翻转即可
第0位翻转:ucLed ^= 0x01
第一位翻转:ucLed ^= 0x20
第二位翻转:ucLed ^= 0x40
某一位翻转:ucLed ^= (1<< x) 将第x位翻转(0-7)
某一位清0: ucLed &= ~(1<<3) 第3位清0(0-7)
某一位置1: ucLed | = (1<< 3)
让led2闪烁5次,即翻转10次
void Led_Proc(void)
{
if((uwTick - uwTick_Led_Set_Point)<=200) return;//减速函数
uwTick_Led_Set_Point = uwTick;
if(led2 ==1)
{
if(led2_num--) // 10次 0.2进来判断10
{
ucLed ^= 0x02;
}
if(led2_num == 0)
{
led2_num =10;
led2 = 0;
ucLed &= ~(1<<1); //清零
}
}
LED_Disp(ucLed);
}
注意:当闪烁5次以后,要将相应的标志恢复位原来前的现场!!!!