文章目录
一、595级联
1.题目要求
STM32单片机,以及三个LED灯对应红黄绿灯,IIC的OLED显示屏,温湿度传感器DHT11,两个独立按键和两个595级联控制的数码管。
OLED显示屏显示内容如下:
(1)TEMP温度
(2)HUMI湿度
(3)MODE(当前倒计时模式,A,B二选一)
(4)CYZS穿衣指数(根据当前温度数值所处区间分析出来的一个值)
其中模式区分如下:
穿衣指数定义如下:
两个按键分别是模式切换按键和模拟故障按键
- A和B指的都是倒计时模式,A.B存在的意义是在于描述倒计时的“倒计时时间”的不同,模式切换是按key0,按下后会在一个循环完成后,从下一个循环开始会用另一个模式来
- 故障模式就是,按下key1令三个灯都亮,数码管显示88,再按一次key1恢复正常
2.思路
这里的数码管是淘宝买的,实际Proteus仿真里面刚好和这个一样的,所以我直接采用两个独立的7段数码管来模拟。
重点讲一下595芯片,其实之前的基于51单片机的点阵显示的proteus仿真(附源码)也有提到过了。
时序图:(这里的时序图和我找的引脚名称不一样,应该是不同厂家命名不一样而已,作用是一样的。)
真值表:
通过上面的时序图和真值表,我们知道它的工作原理是
- 通过DS数据输入引脚,将要传输的位数据输入到595上;
- 在SH_CP(也就是移位寄存器时钟输入)为上升沿的时候,将数据移入到74HC595的移位寄存器上,这里注意先送高位;
- 在ST_CP(也就是锁存器时钟输入)为上升沿的时候,将移位寄存器的数据输出到存储寄存器上,也就是输出端Q0~Q7。
- 当MR为高电平,数据在SHCP上升沿进入移位寄存器,在STCP上升沿输出到并行端口,OE为使能端,低电平有效,当OE为低时,输出使能,为高关闭使能,并不影响其他输入端。
一句话概括就是在正常使用时ST_CP为低电平, /OE为低电平。从DS每输入一位数据,串行输入时钟SH_CP上升沿有效一次,直到八位数据输入完毕,输出时钟ST_CP上升沿有效一次,此时,输入的数据就被送到了输出端。
级联的具体连接方式是将上一个74HC595的Q7’输出端口连接到下一个74HC595的串行输入端口DS上,这样就可以通过移位寄存器时钟和锁存器将数据从一个74HC595移位到下一个74HC595,并最终输出到扩展的输出端口上。
3.仿真图
3.1 未仿真时
想上传仿真的视频,但是视频导进去一直进度为0,之前还可以的,现在不行了。
3.2 模式A
3.2 模式B
3.3 故障模式
4.仿真程序
4.1 程序说明
主控芯片:STM32F103C8
HICK:64MHZ
Systick: 1ms
串口调试:Uart1:9600(PA9:tx1,PA10:rx1)
KEY按键:
KEY1(PB13)
KEY2(PB14)
温湿度传感器DHT11:
DATA(PA11)
红灯:LED1(PA1)
黄灯:LED2(PA4)
绿灯:LED3(PA6)
OLED显示屏:SCL(PA7),SDA(PA5)
74HC595:
SHCP(PB0)
DS (PB1)
STCP(PB3)
4.2 主函数
/* Includes ------------------------------------------------------------------*/
#include "Drv_UserSystem.h"
/**
* @brief main function.
* @param none
* @retval none
*/
int main(void)
{
UserSystemInit();//用户配置初始化
while (1)
{
if (stSysTime.flg._10ms + TEN_MILLISECOND < Time_millis()) //10ms
{
stSysTime.flg._10ms = Time_millis();
Key_Scan();//按键扫描
DHT11_Collect_data();//DHT11采集温度,湿度
OLED_Handel();//OLED显示
}
if (stSysTime.flg._100ms + BEST_MILLISECOND < Time_millis()) //100ms
{
stSysTime.flg._100ms = Time_millis();
IWDG_ReloadCounter();//清开门狗
}
if (stSysTime.flg._1s + THOUSAND_MILLISECOND < Time_millis()) //1s
{
stSysTime.flg._1s = Time_millis();
Led_Scan();//灯光扫描
Show_Nixie_tube();//数码管显示
}
}
}
4.3 数码管显示函数
/*******************************************************************************
* 函数名:Show_Nixie_tube
* 描述 :数码管显示
* 输入 :void
* 输出 :void
* 调用 :1s
* 备注 :
*******************************************************************************/
void Show_Nixie_tube(void)
{
if(!key_breakdown)//模拟故障
{
Actuate_74HC595(smgduan[Time_decade],smgduan[Time_unit]);
if(Countdown_Time == 0)
{
Countdown_Time = 0;
Time_decade = 0;
Time_unit = 0;
}
else
{
Countdown_Time--;
Time_decade = Countdown_Time / 10;
Time_unit = Countdown_Time % 10;
}
}
else
{
Actuate_74HC595(smgduan[8],smgduan[8]);
}
// printf("Countdown_Time = %d\r\n",Countdown_Time);
}
4.4 LED扫描函数
/*******************************************************************************
* 函数名:Led_Scan
* 描述 :灯光扫描
* 输入 :void
* 输出 :void
* 调用 :内部调用
* 备注 :1s
*******************************************************************************/
void Led_Scan(void)
{
if(key_breakdown)//模拟故障
{
LED1_On();
LED2_On();
LED3_On();
breakdown_flag = 1;
}
else
{
if(breakdown_flag)
{
LED1_Off();
LED2_Off();
LED3_Off();
breakdown_flag = 0;
}
if((key_mode == 1) && (End_modeA == 1))//模式B且上一次模式执行结束
{
switch(step_b)
{
case 0:
Led_Status(1);
count_b--;
if(count_b == 5)
{
step_b = 1;
count_b = 6;
Countdown_Time = 6;
}
break;
case 1:
Led_Status(4);
count_b--;
if(count_b == 0)
{
step_b = 2;
count_b = 6;
Countdown_Time = 6;
flicker_flag = 0;
}
break;
case 2:
Led_Status(2);
count_b--;
if(count_b == 0)
{
step_b = 3;
count_b = 26;
Countdown_Time = 26;
}
break;
case 3:
Led_Status(3);
count_b--;
if(count_b == 6)
{
step_b = 4;
count_b = 6;
Countdown_Time = 6;
}
break;
case 4:
Led_Status(5);
count_b--;
if(count_b == 0)
{
step_b = 5;
count_b = 6;
Countdown_Time = 6;
flicker_flag = 0;
}
break;
case 5:
Led_Status(2);
count_b--;
if(count_b == 0)
{
if(key_mode_flag)
{
key_mode = 1;
End_modeB = 0;
count_b = 46;
Countdown_Time = 46;
flicker_flag = 0;
}
else
{
key_mode = 0;
End_modeB = 1;
count_a = 31;
Countdown_Time = 31;
flicker_flag = 0;
}
step_b = 0;
}
break;
}
}
else if((key_mode == 0) && (End_modeB == 1))//模式A且上一次模式执行结束
{
switch(step_a)
{
case 0:
Led_Status(1);
count_a--;
if(count_a == 5)
{
step_a = 1;
count_a = 6;
Countdown_Time = 6;
}
break;
case 1:
Led_Status(4);
count_a--;
if(count_a == 0)
{
step_a = 2;
count_a = 6;
Countdown_Time = 6;
flicker_flag = 0;
}
break;
case 2:
Led_Status(2);
count_a--;
if(count_a == 0)
{
step_a = 3;
count_a = 21;
Countdown_Time = 21;
}
break;
case 3:
Led_Status(3);
count_a--;
if(count_a == 6)
{
step_a = 4;
count_a = 6;
Countdown_Time = 6;
}
break;
case 4:
Led_Status(5);
count_a--;
if(count_a == 0)
{
step_a = 5;
count_a = 6;
Countdown_Time = 6;
flicker_flag = 0;
}
break;
case 5:
Led_Status(2);
count_a--;
if(count_a == 0)
{
if(key_mode_flag)
{
key_mode = 1;
End_modeA = 1;
count_b = 46;
Countdown_Time = 46;
flicker_flag = 0;
}
else
{
key_mode = 0;
End_modeA = 0;
count_a = 31;
Countdown_Time = 31;
flicker_flag = 0;
}
step_a = 0;
}
break;
}
}
}
}
二、总结
今天主要讲了基于STM32的595级联的Proteus仿真。
感谢你的观看!
有需要定制proteus仿真可以联系,谢谢