51_LanQiaoBei/题目/真题/10 第十届国赛_左岚/第十届国赛/User/main.c
2025-04-13 01:02:19 +08:00

333 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.

#include "main.h"
/* LED显示 */
uchar ucLed[8] = {0, 0, 0, 0, 0, 0, 0, 0};
/* 数码管显示 */
uchar Seg_Buf[8] = {10, 10, 10, 10, 10, 10, 10, 10}; // 数码管显示的值
uchar Seg_Pos; // 数码管指示
uchar Seg_Point[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // 某位是否显示小数点
/* 串口方面 */
uchar Uart_Buf[6]; // 串口接收到的数据
uchar Uart_Rx_Index; // 串口接收到的数据的指针
/* 时间方面 */
uint time_all_1s;
uint long_press_1s_12; // 长按1s的计时器
uint long_press_1s_13; // 长按1s的计时器
uchar Sys_Tick; // 嘀嗒计时,超时解析
/* 界面 */
uchar Seg_show_mode; // 0 数据 1 参数
uchar Data_show_mode; // 0 温度 1 距离 2 变更次数
uchar Para_show_mode; // 0 温度 1 距离
uchar Out_mode; // 0 启动 1 停止
/* 数据 */
uint T_value_100x; // 温度的100倍
uchar Dis_value; // 距离
uint Change_times; // 变更次数
uchar Para_T = 30; // 温度参数
uchar Para_Dis = 35; // 距离参数
uchar Para_T_temp;
uchar Para_Dis_temp;
/* 判断*/
bit press_12; // 按下12
bit press_13; // 按下13
bit Uart_flag; // 是否接收到信息
bit out_range; // 是否超出范围
bit hot_T; // 是否温度过高
/* 数据处理函数 */
void Data_Proc() {
if (time_all_1s % 100 == 0) {
// 距离读取
Dis_value = Ut_Wave_Data();
out_range = Dis_value > Para_Dis;
}
if (time_all_1s % 500 == 0) {
// 温度读取
T_value_100x = rd_temperature() * 100;
hot_T = (T_value_100x > Para_T * 100);
}
}
/* 键盘处理函数 */
void Key_Proc() {
static uchar Key_Val, Key_Down, Key_Up, Key_Old;
if (time_all_1s % 10) return;
Key_Val = Key_Read();
Key_Down = Key_Val & (Key_Old ^ Key_Val);
Key_Up = ~Key_Val & (Key_Old ^ Key_Val);
Key_Old = Key_Val;
if (Key_Down == 12) {
press_12 = 1; // 按下12
}
// 到达时间
if (long_press_1s_12 >= 1000) {
press_12 = 0;
// 执行长按1s的操作
Change_times = 0;
}
// 抬起12并且时间没有到达1s
if (Key_Up == 12 && press_12) {
press_12 = 0; // 松开12
// 时间未到就松开,代表短按
switch (Seg_show_mode) {
case 0:
/* 数据 */
Data_show_mode = (++Data_show_mode) % 3;
break;
case 1:
/* 参数 */
Para_show_mode = (++Para_show_mode) % 2;
break;
}
}
if (Key_Down == 13) {
press_13 = 1; // 按下13
}
// 到达时间
if (long_press_1s_13 >= 1000) {
press_13 = 0;
// 执行长按操作
Out_mode = (++Out_mode) % 2;
}
// 抬起13并且时间没有到达1s
if (Key_Up == 13 & press_13) {
press_13 = 0; // 松开13
// 时间未到就松开,代表短按
Seg_show_mode = (++Seg_show_mode) % 2;
Data_show_mode = 0;
Para_show_mode = 0;
if (Seg_show_mode == 1) {
// 进入参数页面
Para_Dis_temp = Para_Dis;
Para_T_temp = Para_T;
} else {
// 退出参数页面
if (Para_Dis_temp != Para_Dis || Para_T_temp != Para_T) {
Change_times = (Change_times == 65535) ? 65535 : Change_times + 1;
EEPROM_Write(&Change_times, 0, 2);
}
Para_Dis = Para_Dis_temp;
Para_T = Para_T_temp;
}
}
switch (Para_show_mode) {
case 0:
/* 温度 */
if (Key_Down == 16) Para_T = (Para_T <= 1) ? 99 : Para_T - 2;
if (Key_Down == 17) Para_T = (Para_T >= 98) ? 0 : Para_T + 2;
break;
case 1:
/* 距离 */
if (Key_Down == 16) Para_Dis = (Para_Dis <= 4) ? 99 : Para_Dis - 5;
if (Key_Down == 17) Para_Dis = (Para_Dis >= 95) ? 0 : Para_Dis + 5;
break;
}
}
/* 数码管处理函数 */
void Seg_Proc() {
if (time_all_1s % 20) return;
switch (Seg_show_mode) {
case 0:
/* 数据 */
switch (Data_show_mode) {
case 0:
/* 温度 */
Seg_Point[5] = 1;
Seg_Buf[0] = 11; // C
Seg_Buf[1] = Seg_Buf[2] = Seg_Buf[3] = 10;
Seg_Buf[4] = T_value_100x / 1000 % 10;
Seg_Buf[5] = T_value_100x / 100 % 10;
Seg_Buf[6] = T_value_100x / 10 % 10;
Seg_Buf[7] = T_value_100x % 10;
break;
case 1:
/* 距离 */
Seg_Point[5] = 0;
Seg_Buf[0] = 12; // L
Seg_Buf[1] = Seg_Buf[2] = Seg_Buf[3] = Seg_Buf[4] = Seg_Buf[5] = 10;
Seg_Buf[6] = Dis_value / 10 % 10;
Seg_Buf[7] = Dis_value % 10;
break;
case 2:
/* 变更次数 */
Seg_Point[5] = 0;
Seg_Buf[0] = 13; // n
Seg_Buf[1] = Seg_Buf[2] = 10;
Seg_Buf[3] =
(Change_times / 10000 % 10 == 0) ? 10 : Change_times / 10000 % 10;
Seg_Buf[4] = (Seg_Buf[3] == 10 && (Change_times / 1000 % 10 == 0))
? 10
: Change_times / 1000 % 10;
Seg_Buf[5] = (Seg_Buf[4] == 10 && (Change_times / 100 % 10 == 0))
? 10
: Change_times / 100 % 10;
Seg_Buf[6] = (Seg_Buf[5] == 10 && (Change_times / 10 % 10 == 0))
? 10
: Change_times / 10 % 10;
Seg_Buf[7] = Change_times % 10;
break;
}
break;
case 1:
/* 参数 */
Seg_Point[5] = 0;
Seg_Buf[0] = 14; // P
Seg_Buf[1] = Seg_Buf[2] = 10;
Seg_Buf[3] = Para_show_mode + 1;
Seg_Buf[4] = Seg_Buf[5] = 10;
switch (Para_show_mode) {
case 0:
/* 温度 */
Seg_Buf[6] = Para_T_temp / 10 % 10;
Seg_Buf[7] = Para_T_temp % 10;
break;
case 1:
/* 距离 */
Seg_Buf[6] = Para_Dis_temp / 10 % 10;
Seg_Buf[7] = Para_Dis_temp % 10;
break;
}
break;
}
}
/* LED处理函数 */
void Led_Proc() {
switch (Out_mode) {
case 0:
/* 启动 */
if (out_range)
Da_Write(4 * 51); // 超出范围输出4V
else
Da_Write(2 * 51); // 没超范围输出2V
break;
case 1:
/* 停止 */
Da_Write(0.4 * 51); // 停止状态输出0.4V
break;
}
ucLed[0] = hot_T;
ucLed[1] = !out_range;
ucLed[2] = !Out_mode;
}
/* 串口处理函数 */
void Uart_Proc() {
if (Uart_Rx_Index == 0) return;
// 超过10ms没有收到数据
if (Sys_Tick >= 10) {
Sys_Tick = Uart_flag = 0;
if (Uart_Buf[0] == 'S' && Uart_Buf[1] == 'T') {
printf("$%bu,%5.2f\r\n", Dis_value, (float)T_value_100x / 100.0);
} else if (Uart_Buf[0] == 'P' && Uart_Buf[1] == 'A' && Uart_Buf[2] == 'R' &&
Uart_Buf[3] == 'A') {
printf("#%bu,%bu\r\n", Para_Dis, Para_T);
} else {
printf("ERROR\r\n");
}
memset(Uart_Buf, 0, Uart_Rx_Index);
Uart_Rx_Index = 0;
}
}
/* 定时器0中断初始化 */
void Timer0_Init(void) // 1毫秒@12.000MHz
{
AUXR &= 0x7F; // 定时器时钟12T模式
TMOD &= 0xF0; // 设置定时器模式
TL0 = 0x18; // 设置定时初始值
TH0 = 0xFC; // 设置定时初始值
TF0 = 0; // 清除TF0标志
TR0 = 1; // 定时器0开始计时
ET0 = 1;
EA = 1;
}
/* 定时器0中断函数 */
void Timer0_ISR(void) interrupt 1 {
uchar i;
if (++time_all_1s == 1000) time_all_1s = 0;
// 长按计时部分
if (press_12) {
if (++long_press_1s_12 >= 1000) {
long_press_1s_12 = 1001;
}
} else {
long_press_1s_12 = 0;
}
if (press_13) {
if (++long_press_1s_13 >= 1000) {
long_press_1s_13 = 1001;
}
} else {
long_press_1s_13 = 0;
}
// 串口嘀嗒部分
if (Uart_flag) Sys_Tick++;
Seg_Pos = (++Seg_Pos) % 8;
Seg_Disp(Seg_Pos, Seg_Buf[Seg_Pos], Seg_Point[Seg_Pos]);
for (i = 0; i < 8; i++) Led_Disp(i, ucLed[i]);
}
/* 串口中断服务函数 */
void Uart_ISR(void) interrupt 4 {
if (RI == 1) // 串口接收到数据
{
Uart_flag = 1;
Sys_Tick = 0; // 接受计时
Uart_Buf[Uart_Rx_Index] = SBUF;
Uart_Rx_Index++;
RI = 0;
}
if (Uart_Rx_Index > 6) Uart_Rx_Index = 0;
}
void Delay750ms(void) //@12.000MHz
{
unsigned char data i, j, k;
_nop_();
_nop_();
i = 35;
j = 51;
k = 182;
do {
do {
while (--k);
} while (--j);
} while (--i);
}
uchar passwd = 155;
uchar input_passwd;
void main() {
System_Init();
Timer0_Init();
Uart1_Init();
rd_temperature();
Delay750ms();
EEPROM_Read(&input_passwd, 8, 1); // 用不会写入的地方做校验
if (input_passwd != passwd) // 校验失败之前未写入数据1/256概率出问题
{
EEPROM_Write(&passwd, 8, 1);
} else // 校验通过,读取我们需要的数据
{
EEPROM_Read(&Change_times, 0, 2);
}
T_value_100x = rd_temperature() * 100;
while (1) {
Data_Proc();
Key_Proc();
Seg_Proc();
Uart_Proc();
Led_Proc();
}
}