//硬件:msp430f5529、dht22、LCD1602、蜂鸣器、烟雾传感器、蓝牙模块。
//功能:读取温湿度、烟雾浓度显示到屏幕;
//按键调节三个报警数值;
//温度、湿度、烟雾浓度,任意一个大于报警数值就蜂鸣器报警;
//单片机将温度、湿度、烟雾浓度,通过蓝牙模块,发送到电脑端显示。
//电脑端也可以调节三个报警数值。
cpp//PCF8574 LCD1602----MSP430F5529
//GND----------------GND
//VCC----------------3.3v
//SDA----------------P2.4
//SCL----------------P2.5
//HC05 蓝牙----------MSP430F5529
//GND----------------GND
//VCC----------------3.3v
//RX-----------------P3.3 T
//TX-----------------P3.4 R
//PM2烟雾传感器 0~3.3v电压转为ppm单位 20~20000ppm
//DHT22--------------MSP430F5529
//GND----------------GND
//VCC----------------3.3v
//DAT----------------P2.3
//烟雾---------------MSP430F5529
//GND----------------GND
//VCC----------------3.3v
//A0-----------------P6.5
//蜂鸣器-------------MSP430F5529
//GND----------------GND
//VCC----------------3.3v
//DAT----------------P1.6
//按键----------------MSP430F5529
//KEY1----------------P1.2
//KEY2----------------P1.3
//KEY3----------------P1.4
//KEY4----------------P1.5
//GND-----------------GND
//板子自己有的按键
//KEY5----------------P1.1
//KEY6----------------P2.1
cppunsigned char get_key(void) //声明一个函数,返回值类型为 unsigned char,函数名为 get_key,参数列表为空
{
unsigned char key; //声明一个名为 key 的无符号字符变量
if ((P1IN & BIT2) == 0) //如果 P1IN 寄存器的第二位是 0,说明按键1被按下
{
delay_ms(10); //延时 10 毫秒,以确保读取的值稳定
if ((P1IN & BIT2) == 0) //再次检测按键1是否被按下
{
key = 1; //将 key 设置为 1,表示按下了按键1
while ((P1IN & BIT2) == 0)
//等待按键1松开
;
}
}
else if ((P1IN & BIT3) == 0) //如果按键1未被按下,检测按键2是否被按下
{
delay_ms(10); //同样进行延时
if ((P1IN & BIT3) == 0) //检测按键2是否被按下
{
key = 2; //将 key 设置为 2,表示按下了按键2
while ((P1IN & BIT3) == 0)
//等待按键2松开
;
}
}
else if ((P1IN & BIT4) == 0)
{
delay_ms(10);
if ((P1IN & BIT4) == 0)
{
key = 3;
while ((P1IN & BIT4) == 0)
;
}
}
else if ((P1IN & BIT5) == 0)
{
delay_ms(10);
if ((P1IN & BIT5) == 0)
{
key = 4;
while ((P1IN & BIT5) == 0)
;
}
}
else if ((P1IN & BIT1) == 0)
{
delay_ms(10);
if ((P1IN & BIT1) == 0)
{
key = 5;
while ((P1IN & BIT1) == 0)
;
}
}
else if ((P2IN & BIT1) == 0)
{
delay_ms(10);
if ((P2IN & BIT1) == 0)
{
key = 6;
while ((P2IN & BIT1) == 0)
;
}
}
else
{
key = 0;
}
return key;
}
u8 data[5];
u16 shidu, wendu, yanwu;
u16 shidu_baojing = 900, wendu_baojing = 400, yanwu_baojing = 10000;
u8 disp[20];
u8 count = 0;
u8 timecnt = 0;
u8 keyvalue = 0;
void disp_line1(void) // 定义名为disp_line1的函数
{
count = 0; // 初始化计数器
disp[count++] = wendu % 1000 / 100 + '0'; // 将温度百位数字转换为字符存入显示缓存数组,计数器+1
disp[count++] = wendu % 100 / 10 + '0'; // 将温度十位数字转换为字符存入显示缓存数组,计数器+1
disp[count++] = 'C'; // 存入字符'C',表示摄氏度,计数器+1
disp[count++] = ' '; // 存入空格字符,计数器+1
disp[count++] = shidu % 1000 / 100 + '0'; // 将湿度百位数字转换为字符存入显示缓存数组,计数器+1
disp[count++] = shidu % 100 / 10 + '0'; // 将湿度十位数字转换为字符存入显示缓存数组,计数器+1
disp[count++] = '%'; // 存入字符'%',表示百分比符号,计数器+1
disp[count++] = ' '; // 存入空格字符,计数器+1
disp[count++] = yanwu % 100000 / 10000 + '0'; // 将烟雾万位数字转换为字符存入显示缓存数组,计数器+1
disp[count++] = yanwu % 10000 / 1000 + '0'; // 将烟雾千位数字转换为字符存入显示缓存数组,计数器+1
disp[count++] = yanwu % 1000 / 100 + '0'; // 将烟雾百位数字转换为字符存入显示缓存数组,计数器+1
disp[count++] = yanwu % 100 / 10 + '0'; // 将烟雾十位数字转换为字符存入显示缓存数组,计数器+1
disp[count++] = yanwu % 10 + '0'; // 将烟雾个位数字转换为字符存入显示缓存数组,计数器+1
disp[count++] = 'p'; // 存入字符'p',表示“ppm”(parts per million),计数器+1
disp[count++] = 0; // 存入字符'\0',表示字符串结束,计数器+1
LCD_write_str(0, 0, disp); // 在LCD屏幕第0行显示disp数组中的内容
}
void send_computer(void)
{
count = 0;
disp[count++] = wendu % 1000 / 100 + '0';
disp[count++] = wendu % 100 / 10 + '0';
disp[count++] = 'C';
disp[count++] = ' ';
disp[count++] = shidu % 1000 / 100 + '0';
disp[count++] = shidu % 100 / 10 + '0';
disp[count++] = '%';
disp[count++] = ' ';
disp[count++] = yanwu % 100000 / 10000 + '0';
disp[count++] = yanwu % 10000 / 1000 + '0';
disp[count++] = yanwu % 1000 / 100 + '0';
disp[count++] = yanwu % 100 / 10 + '0';
disp[count++] = yanwu % 10 + '0';
disp[count++] = 'p';
disp[count++] = '\r';
disp[count++] = '\n';
disp[count++] = 0;
Print_Str(disp);
}
void disp_line2(void)
{
count = 0; //计数器清零
//显示湿度报警值的百位、十位
disp[count++] = shidu_baojing % 1000 / 100 + '0';
disp[count++] = shidu_baojing % 100 / 10 + '0';
disp[count++] = 'C'; //显示'C'
disp[count++] = ' '; //显示空格
//显示温度报警值的百位、十位
disp[count++] = wendu_baojing % 1000 / 100 + '0';
disp[count++] = wendu_baojing % 100 / 10 + '0';
disp[count++] = '%'; //显示'%'
disp[count++] = ' '; //显示空格
//显示烟雾报警值的万位、千位、百位、十位、个位
disp[count++] = yanwu_baojing % 100000 / 10000 + '0';
disp[count++] = yanwu_baojing % 10000 / 1000 + '0';
disp[count++] = yanwu_baojing % 1000 / 100 + '0';
disp[count++] = yanwu_baojing % 100 / 10 + '0';
disp[count++] = yanwu_baojing % 10 + '0';
disp[count++] = 'p'; //显示'p'
disp[count++] = 0; //末尾字符为0
//在LCD的第1行第0列显示字符串disp
LCD_write_str(0, 1, disp);
}
void deal_key(void)
{
// 定义一个函数deal_key,没有返回值,没有参数
if (keyvalue == 1)
{
// 如果keyvalue的值为1
shidu_baojing += 10;
// 湿度报警值加10
if (shidu_baojing > 900)
{
// 如果湿度报警值大于900
shidu_baojing = 900;
// 把湿度报警值设为900
}
}
else if (keyvalue == 2)
{
// 否则,如果keyvalue的值为2
shidu_baojing -= 10;
// 湿度报警值减10
if (shidu_baojing < 100)
{
// 如果湿度报警值小于100
shidu_baojing = 100;
// 把湿度报警值设为100
}
}
else if (keyvalue == 3)
{
// 否则,如果keyvalue的值为3
wendu_baojing += 10;
// 温度报警值加10
if (wendu_baojing > 900)
{
// 如果温度报警值大于900
wendu_baojing = 900;
// 把温度报警值设为900
}
}
else if (keyvalue == 4)
{
// 否则,如果keyvalue的值为4
wendu_baojing -= 10;
// 温度报警值减10
if (wendu_baojing < 100)
{
// 如果温度报警值小于100
wendu_baojing = 100;
// 把温度报警值设为100
}
}
else if (keyvalue == 5)
{
// 否则,如果keyvalue的值为5
yanwu_baojing += 100;
// 烟雾报警值加100
if (yanwu_baojing > 20000)
{
// 如果烟雾报警值大于20000
yanwu_baojing = 20000;
// 把烟雾报警值设为20000
}
}
else if (keyvalue == 6)
{
// 否则,如果keyvalue的值为6
yanwu_baojing -= 100;
// 烟雾报警值减100
if (yanwu_baojing < 200)
{
// 如果烟雾报警值大于200
yanwu_baojing = 200;
// 把烟雾报警值设为200
}
}
}
void contorl_beep(void) // 定义一个名为 contorl_beep 的函数
{
if ((shidu > shidu_baojing) || (wendu > wendu_baojing) // 如果湿度、温度或烟雾任意一个超过了警戒值
|| (yanwu > yanwu_baojing))
{
P1OUT &= ~BIT6; // 将 P1OUT 寄存器的第 6 位设置为 0,表示开启蜂鸣器
}
else // 如果湿度、温度和烟雾都没有超过警戒值
{
P1OUT |= BIT6; // 将 P1OUT 寄存器的第 6 位设置为 1,表示关闭开启蜂鸣器
}
}
/* 烟雾浓度换算 */
static unsigned int yw_ppm_count(unsigned int x1)
{
float a =0 ,b = 0,c = 0,d = 0;
float ax =0 ,bx = 0,cx = 0,dx = 0;
float y;
float x;
x=x1*3.3/4096;
a = x * x * x * x * x;
b = x * x * x * x;
c = x * x * x;
d = x * x ;
ax = 0.0001923 * a;
bx = 0.006017 * b;
cx = 0.07267 * c;
dx = 0.425 * d;
y = ax - bx + cx - dx + (1.267 * x) + 1.209;
y = y * 1000;
return (unsigned int)y;
}
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // 停止看门狗定时器
init_clock(); // 初始化时钟
init_uart(); // 初始化UART串口
init_adc(); // 初始化ADC模块
init_key(); // 初始化按键
init_beep(); // 初始化蜂鸣器
while (DHT22_Init() == 1) // 初始化DHT22温湿度传感器
{
delay_ms(100); // 延时100毫秒
}
delay_ms(1000);
LCD_Init(); // 初始化液晶屏
disp_line2(); // 在液晶屏上显示第二行
_EINT(); // 开启总中断
while (1) // 无限循环
{
delay_ms(10); // 延时10毫秒
timecnt++; // 时间计数器加1
if (timecnt > 200) // 如果时间计数器超过200
{
timecnt = 0; // 重置时间计数器
DHT22_Read_Data(data); // 读取DHT22传感器数据
shidu = data[0]; // 湿度数据
shidu = (shidu << 8) + data[1]; // 拼接数据
wendu = data[2]; // 温度数据
wendu = (wendu << 8) + data[3]; // 拼接数据
yanwu = get_adc(); // 获取烟雾浓度值
//0到4096转为0到20000ppm
yanwu = yw_ppm_count(yanwu); // 将ADC值转换为烟雾浓度值
contorl_beep(); // 控制蜂鸣器
disp_line1(); // 在液晶屏上显示第一行
disp_line2(); // 在液晶屏上显示第二行
send_computer();
}
keyvalue = get_key(); // 获取按键值
if (keyvalue) // 如果有按键按下
{
deal_key(); // 处理按键
disp_line2(); // 在液晶屏上显示第二行
}
}
}
unsigned char revchar = 0; // 定义一个无符号字符变量,初始值为0,用于保存接收到的字符
unsigned char revchar_openflag = 0; // 定义一个无符号字符变量,初始值为0,用于标志接收到的字符是否为有效数据
unsigned char revchar_cnt = 0; // 定义一个无符号字符变量,初始值为0,用于计数接收到的有效数据个数
unsigned char revchar_buffer[20]; // 定义一个无符号字符数组,长度为20,用于存储接收到的有效数据
#pragma vector=USCI_A0_VECTOR // 定义中断函数,当 USCI_A0_VECTOR 中断发生时,执行以下函数
__interrupt void USCI_A0_ISR(void)
{
switch (__even_in_range(UCA0IV, 4))
// 获取 USCI_A0_VECTOR 中断的状态
{
case 0: // Vector 0 - no interrupt,无中断状态
break;
case 2: // Vector 2 - RXIFG,接收到数据的中断状态
revchar = UCA0RXBUF; // 读取 USCI_A0_VECTOR 的接收缓冲区数据到变量 revchar
if (revchar_openflag) // 如果接收到的字符是有效数据
{
//S889912345 // 检查接收到的数据是否符合特定的格式,如S889912345
if ((revchar >= '0') && (revchar <= '9')) // 如果接收到的数据是数字字符
{
revchar_buffer[revchar_cnt] = revchar - '0'; // 把接收到的数字字符转化为对应的数字存入 revchar_buffer 数组中
revchar_cnt++; // 计数器加1
if (revchar_cnt >= 9) // 如果接收到的数字字符数量达到特定的数量
{
shidu_baojing = revchar_buffer[0] * 100
+ revchar_buffer[1] * 10; // 计算湿度报警值
wendu_baojing = revchar_buffer[2] * 100
+ revchar_buffer[3] * 10; // 计算温度报警值
yanwu_baojing = revchar_buffer[4] * 10000
+ revchar_buffer[5] * 1000 + revchar_buffer[6] * 100
+ revchar_buffer[7] * 10 + revchar_buffer[8]; // 计算烟雾报警值
revchar_openflag = 0; // 清除接收标志
revchar_cnt = 0; // 清除计数器
}
}
else // 如果接收到的字符不是数字字符
{
revchar_openflag = 0; // 清除接收标志
revchar_cnt = 0; // 清除计数器
}
}
if (revchar == 'S')
{
revchar_openflag = 1;
revchar_cnt = 0;
}
break;
case 4:
break; // Vector 4 - TXIFG
default:
break;
}
}
cpphttps://docs.qq.com/sheet/DUEdqZ2lmbmR6UVdU?tab=BB08J2
本文作者:Dong
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC。本作品采用《知识共享署名-非商业性使用 4.0 国际许可协议》进行许可。您可以在非商业用途下自由转载和修改,但必须注明出处并提供原作者链接。 许可协议。转载请注明出处!