

若需要运行源码,需要将控制温湿度传感器以及LCD屏幕(TFTv2.h DHT.h)的头文件添加进工程
主程序初始化
#include <stdint.h>
#include "TFTv2.h"
#include <SPI.h>
#include <DHT.h>
#define DHTPIN 8 // 温湿度传感器连接的引脚
#define DHTTYPE DHT22 // DHT 22 (AM2302)
DHT dht(DHTPIN, DHTTYPE,4);
char sensorPrintout[4];//存储
int count=0;
const int interruptA = 3;// 设置中断Interrupt引脚
const int interruptB = 2;
const int interruptD = 19;
int F[2] = {0,0};//初始化页面状态参量
int S[2] = {0,0};//初始化页面参量
int R = -1;//页面索引参量
int button1 = 3;//管脚号定义,下同
int button2 = 2;
int button4 = 19;
//LED 代码初始化部分
const int ledPin = 13; // led连接的引脚
int ledState = LOW; // led状态,亮或者灭,可以修改
long previousMillis = 0; // 存储最后一次的led状态
// 这里使用了长整型变量,因为使用了ms,瞬间的数值变化非常大。
long interval = 500; // 间隔闪烁的时间长度
unsigned long time_find = 0;
void setup()
{
Serial.begin(9600); //串口初始化
Serial2.begin(9600);//串口初始化
dht.begin();
/* LCD 初始化 */
SPSR |= (1 << SPI2X); // 2x SPI speed
TFT_BL_ON; // turn on the background light
Tft.TFTinit(); //init TFT library
Tft.drawLine(0,0,239,319,RED); //start: (0, 0) end: (239, 319), color : RED
Tft.drawVerticalLine(60,100,100,GREEN); // Draw a vertical line
// start: (60, 100) length: 100 color: green
Tft.drawHorizontalLine(30,60,150,BLUE); //Draw a horizontal line
//start: (30, 60), high: 150, color: blue
Tft.drawCircle(100, 100, 30,YELLOW); //center: (100, 100), r = 30 ,color : YELLOW
Tft.drawCircle(100, 200, 40,CYAN); // center: (100, 200), r = 10 ,color : CYAN
Tft.fillCircle(200, 100, 30,RED); //center: (200, 100), r = 30 ,color : RED
Tft.fillCircle(200, 200, 30,BLUE); //center: (200, 200), r = 30 ,color : BLUE
Tft.drawString("Hello",0,180,3,CYAN); // draw string: "hello", (0, 180), size: 3, color: CYAN
Tft.drawString("World!!",60,220,4,WHITE); // draw string: "world!!", (80, 230), size: 4, color: WHITE
delay(500);
/* LCD 初始化结束 */
pinMode(button1, INPUT); //管脚输入输出方式
pinMode(button2, INPUT);
pinMode(button4, INPUT);
pinMode(ledPin, OUTPUT);
digitalWrite(button1, HIGH);//数字写为高电平
digitalWrite(button2, HIGH);
digitalWrite(button4, HIGH);
attachInterrupt(digitalPinToInterrupt(interruptA), Choose1, FALLING);//中断下降沿触发
attachInterrupt(digitalPinToInterrupt(interruptB), Choose2, FALLING);
attachInterrupt(digitalPinToInterrupt(interruptD), Return_, FALLING);
}
部分运行效果(完整工程在资源里)
二级菜单


三个按键控制菜单,功能分别为:选择功能1,选择功能2,以及返回上一级;
通过三个外部中断对页面状态参量进行控制:
void Choose1(){//确认选择第一个功能
R = R+1;//对状态参量进行操作,进入下一页,即F数组加一位
F[R] = F[R]+1;
}
void Choose2(){//确认选择第二个功能
R = R+1;//对状态参量进行操作,进入下一页,即S数组加一位
S[R] = S[R]+1;
}
void Return_(){//返回上一级
if(F[R] == 1){//将状态参量退回到上一级
F[R] = F[R]-1;}
else if(S[R] == 1){
S[R] = S[R]-1;}
R = R-1;
}
温湿度传感器

while(F[0] == 1 & F[1] ==0 & S[0] == 0 & S[1] == 1){//进入温湿度传感器界面
float h = dht.readHumidity();// 读温度湿度的取值
// Read temperature as Celsius
float t = dht.readTemperature();
// Read temperature as Fahrenheit
float f = dht.readTemperature(true);
// Check if any reads failed and exit early (to try again).
float hi = dht.computeHeatIndex(f, h);
Tft.fillScreen(); //清屏
Tft.drawString("Humidity: ",0,0,2,CYAN); // 可修改坐标 大小 颜色等
Tft.drawFloat(h,3,60,50,1,WHITE);
Tft.drawString("Temperature: ",0,100,2,CYAN);
Tft.drawFloat(t,3,60,150,1,WHITE);
Tft.drawString("Heat index:",0,200,2,CYAN);
Tft.drawFloat(hi,3,60,250,1,WHITE);
delay(500);}
可靠通信(停止等待协议)
停止等待
当U1收到U2的ACK后才会发送下一次传感器采集到的数据

超时重传
当关闭U2后,U1到达设定的超时时间后,进行重传操作,直到收到U2的确认收到的信息

while(F[0] == 1 & F[1] == 1 & S[0] == 0 & S[1] == 0){//进入光敏传感器功能,同时进行串口可靠通信
String sensorVal = String(analogRead(A0));//读取模拟值
if(Serial2.find("ack")){//若收到接收端的ack确认信息
time_find = millis();//记录更新最近一次收到确认的时间信息
Serial2.print(sensorVal);
Tft.fillScreen();
Tft.drawString("Data Transmitted!",0,0,2,CYAN);//收到确认后,显示可视化信息,再发送下一次数据
delay(125);
}
unsigned long time_now = millis();//读取现在时钟信息
if(time_now - time_find > 3000){//设置超时时间3秒
Serial2.print(sensorVal);//3秒后再发送一次
Tft.fillScreen();
Tft.drawString("Timeout!",50,0,2,CYAN);//显示超时可视化信息
time_find = time_now;//存储最新一次执行超时重传的时间实现重新计时
delay(125);}
sensorVal.toCharArray(sensorPrintout, 4);//U1 LCD显示出现在传感器的值
Tft.fillScreen();
Tft.drawString("Sensor Data :",0,0,2,CYAN);//显示字符
Tft.drawString(sensorPrintout,0,100,2,CYAN);
delay(125);
}
对于U1来说,只有收到ack确认后才发送下一次的数据,不然就会超时重传。设置变量time_now = millis() 来记录当前运行的总时间,这个变量主程序每循环一次就会更新一次。然后设置变量time_find = millis() (time_find初始化为0)来记录最新一次收到接收端发来的ack并传输数据的时间点。在主程序中每运行一次就会比较time_now – time_find 是否大于超时时间interval,本工程中设置超时时间为3秒,若大于超时时间则重传并LCD显示“Timeout!”,并将此时的time_now赋给time_find来存储最新一次执行超时重传的时间实现重新计时。文章来源:https://www.toymoban.com/news/detail-569388.html
char sensorPrintout1[4];
void setup()
{
Serial.begin(9600);
Serial1.begin(9600);
//Serial.setTimeout(2000);
Serial.print("ack");
}
void loop()
{
if(Serial.available()>0){
Serial.readBytes(sensorPrintout1,4);
Serial1.println(sensorPrintout1);
Serial.print("ack");
}
}
当U2收到U1发来的数据时,使用readBytes函数读取U1通过串口发来的字符串数据,并存储到sensorPrintout1数组中,并将此数据通过串口1打印出来,通过连接的虚拟终端显示。同时通过串口向U1发送“ack”确认字段,并等待下一次数据的到来。文章来源地址https://www.toymoban.com/news/detail-569388.html
如有任何疑问可以留言
声明:只用作分享学习,共同进步,其他不做任何用途
到了这里,关于Proteus平台下基于Arduino的通过UART串口可靠通信系统仿真、传感器数据采集、以及LCD屏幕二级菜单功能实现(附工程源码、设计报告)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!