基于STM32的595级联的Proteus仿真

19 篇文章 3 订阅


一、595级联

1.题目要求

STM32单片机,以及三个LED灯对应红黄绿灯,IIC的OLED显示屏,温湿度传感器DHT11,两个独立按键和两个595级联控制的数码管。

OLED显示屏显示内容如下:
(1)TEMP温度
(2)HUMI湿度
(3)MODE(当前倒计时模式,A,B二选一)
(4)CYZS穿衣指数(根据当前温度数值所处区间分析出来的一个值)

其中模式区分如下:
在这里插入图片描述

穿衣指数定义如下:
在这里插入图片描述
两个按键分别是模式切换按键和模拟故障按键

  1. A和B指的都是倒计时模式,A.B存在的意义是在于描述倒计时的“倒计时时间”的不同,模式切换是按key0,按下后会在一个循环完成后,从下一个循环开始会用另一个模式来
  2. 故障模式就是,按下key1令三个灯都亮,数码管显示88,再按一次key1恢复正常

2.思路

这里的数码管是淘宝买的,实际Proteus仿真里面刚好和这个一样的,所以我直接采用两个独立的7段数码管来模拟。

在这里插入图片描述
重点讲一下595芯片,其实之前的基于51单片机的点阵显示的proteus仿真(附源码)也有提到过了。

在这里插入图片描述

时序图:(这里的时序图和我找的引脚名称不一样,应该是不同厂家命名不一样而已,作用是一样的。)

在这里插入图片描述

真值表:
在这里插入图片描述
通过上面的时序图和真值表,我们知道它的工作原理是

  1. 通过DS数据输入引脚,将要传输的位数据输入到595上;
  2. 在SH_CP(也就是移位寄存器时钟输入)为上升沿的时候,将数据移入到74HC595的移位寄存器上,这里注意先送高位;
  3. 在ST_CP(也就是锁存器时钟输入)为上升沿的时候,将移位寄存器的数据输出到存储寄存器上,也就是输出端Q0~Q7。
  4. 当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仿真可以联系,谢谢

在这里插入图片描述

  • 10
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是关于STM32定时器级联的介绍: STM32定时器级联是指将多个定时器连接在一起,形成一个更长的计数器。这种级联方式可以扩展计数器的位数,从而扩展计时范围。在STM32中,定时器级联可以通过将两个通用定时器(TIM)连接在一起来实现。 具体实现步骤如下: 1. 配置第一个定时器(TIM1)和第二个定时器(TIM2)的基本参数,包括时钟源、预分频器、计数模式等。 2. 配置第一个定时器(TIM1)的输出比较模式,使其输出一个特定的PWM波形。 3. 配置第二个定时器(TIM2)的输入捕获模式,使其可以捕获第一个定时器(TIM1)的PWM波形。 4. 将第二个定时器(TIM2)的时钟源设置为第一个定时器(TIM1)的输出,这样第二个定时器(TIM2)就可以根据第一个定时器(TIM1)的PWM波形进行计数。 5. 在程序中读取第一个定时器(TIM1)和第二个定时器(TIM2)的计数值,将它们相加即可得到一个更长的计数器。 下面是一个示例代码,演示了如何将两个定时器级联在一起: ```c #include "stm32f4xx.h" void TIM_Config(void); int main(void) { TIM_Config(); while (1) { uint32_t count1 = TIM_GetCounter(TIM1); uint32_t count2 = TIM_GetCounter(TIM2); uint32_t total_count = (count1 << 16) | count2; // 将两个计数器的值相加,得到一个更长的计数器 } } void TIM_Config(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 | RCC_APB2Periph_TIM2, ENABLE); TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; TIM_ICInitTypeDef TIM_ICInitStructure; // 配置TIM1 TIM_TimeBaseStructure.TIM_Period = 999; // PWM周期为1000个时钟周期 TIM_TimeBaseStructure.TIM_Prescaler = 83; // 时钟预分频器为84 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 499; // 占空比为50% TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC1Init(TIM1, &TIM_OCInitStructure); TIM_Cmd(TIM1, ENABLE); // 配置TIM2 TIM_TimeBaseStructure.TIM_Period = 0xFFFF; // 计数器最大值为65535 TIM_TimeBaseStructure.TIM_Prescaler = 0; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStructure.TIM_ICFilter = 0x0; TIM_ICInit(TIM2, &TIM_ICInitStructure); TIM_SelectInputTrigger(TIM2, TIM_TS_TI1FP1); TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset); TIM_Cmd(TIM2, ENABLE); } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaobuding_QAQ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值