完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
1.实验要求:
(1)在STM32平台下,设计一个丁字路***通控制系统; (2)利用10个LED发光二极管来表示交通灯的状态,用74HC595驱动芯片驱动两位7段数码管来显示倒计时; (3)丁字路口分成主干道和支干道,主干道放行时间35s,支干道放行时间25s; (4)通过按键实现整体清零、修改放行时长以及控制特殊情况(主干道和支干道均显示红灯或黄灯)等功能; 2.系统总体设计 (1)系统框图 (2)软件流程图 3.参考代码 /** ******************************************************************************** * 这是一个模拟交通信号灯的实验程序 * (1)利用9个LED发光二极管来表示交通灯的状态,用两位7段数码管来显示倒计时; * (2)丁字路口分成主干道和支干道,主干道放行时间35s,支干道放行时间25s; * (3)通过按键实现整体清零、修改放行时长以及控制特殊情况(主干道和支干道均显示红灯或黄灯)等功能; * (4)加分项:自行增加其他功能。 * * * ******************************************************************************** * 2020/7/1第次修改:加入数码管的驱动 * 使用IO直接驱动 * PB8--PB15用于数码管段码输出 * PB0,PB1用于数码管位码输出 * * 2020/7/2第2次修改:加入LED的驱动 * PA0--PA8,PA11用于交通灯显示 * PA15状态显示,亮:可修改当前计数值 * * 2020/7/2第3次修改:加入HC595驱动,使用HC595驱动数码管显示------没实现,有BUG * HC595的连接 DIO--PA12,SCLK---PA14,RCLK---PA13 * * 2020/7/2第3次修改:加入外部中断按键 * PE2---KEY_INT PE3----KEYCOM * 2020/7/2第4次修改,中断中实现计数的加减 * 2020/7/2第4次修改,所有初始化函数的相关引脚进行了宏定义,完善相关注释 * 2020/7/3第5次修改,增加了TM1638驱动动程序 * STB--PB12,CLK--PB11,DIO--PB14 * * 2020/7/3第6次修改,增加了LED交通灯驱动程序 * 2020/7/3第7次,最后一次修改 * 2020/7/6第8次,把显示程序调到了定时器3中断中,实现通过变量a来延长支干放行时间 * 2020/7/6第9次,使用从洋桃电子学到的方法----MENU菜单切换的方法,来优化 * 2020/7/6第10次 实现通过变量a,b来延长主干,支干放行时间 * 2020/7/7第11次 实现通过按键0---3来实现主干,支干放行时长和紧急情况显示 * 按键0---3分别对应PB0---PB3 * 交换了LEDB_G0,LEDB_R0的引脚 * 2020/7/8第12次 修复了595驱动程序,实现595驱动数码管显示 ******************************************************************************** **********************************引脚连接图************************************* 基于普中HC6800开发板的交通模块: * * * * * * * * LEDQ_R0 LEDQ_G0 LEDB_R1 LEDB_Y1 LEDB_G1 LEDQ_R1 LEDQ_Y1 LEDQ_G1 PA0 PA1 PA7 PA8 PA11 PA2 PA3 PA4 * LEDB_G0 PA5 * LEDB_R0 PA6 ******************************************************************************** */ #include "..Usertm1638tm1638.h" #include "stm32f10x.h" #include "usart.h" #include "bsp_led.h" #include "delay.h" #include "bsp_BasicTim.h" #include "bsp_key.h" #include "hc595.h" void In_Urgency(void); void Out_Urgency(void); void dispaly_xx(u8 num); u8 count=0; //初始化过程中会产生一次中断,所以上电瞬间显示34 u8 a=0; //主干放行时间延长,主干绿灯时间延长 u8 b=0; //支干放行时间延长,支干绿灯时间延长 u8 MENU=0; int main(void) { USART1_Init(9600); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); LED_GPIO_Config(); KEY_GPIO_Config(); HC595_Config(); TIM3_Int_Init(9999,7199); MENU=0; while(1) { if(MENU==0) //----------------------------------------------------------------------------MENU=0时,主干到通行 { In_Urgency(); //黄灯等待切换状态,5秒---------------------------[0,5] if(count>=(30+a)){ LEDALLCLOSE(); //--黄灯阶段--// LEDQ_R0(1);//前进路人行道红灯亮 LEDQ_Y1(1);//前进路黄灯亮 LEDQ_G0(0); LEDQ_R1(0); LEDQ_G1(0); LEDB_R0(1);//宝华路人行道红灯亮 LEDB_R1(1);//宝华路红灯亮 LEDB_G0(0); LEDB_G1(0); LEDB_Y1(0); }else{ LEDALLCLOSE(); //前进路通行----------------------[6,35] LEDQ_G1(1);//前进路绿灯亮 LEDQ_R0(1);//前进路人行道红灯亮 LEDQ_G0(0); LEDQ_R1(0); LEDQ_Y1(0); LEDB_R1(1);//宝华路红灯亮 LEDB_G0(1);//宝华路人行道绿灯亮 LEDB_R0(0); LEDB_G1(0); LEDB_Y1(0); } dispaly_xx(35+a); if(count==(35+a)){ MENU=1;count=0;} if(READKEY3==0){ delay_ms(10); //按键2,切换到MENU=2,设置主干放行时长 if(READKEY3==0) { MENU=2;} } } if(MENU==1) //----------------------------------------------------------------------------MENU=1时,支干到通行 { In_Urgency(); //黄灯等待切换状态,5秒-------------------------------[0,5] if(count>=(20+b)) { LEDALLCLOSE(); //--宝华路黄灯阶段--// LEDQ_R0(1);//前进路人行道红灯亮 LEDQ_R1(1);//前进路红灯亮 LEDQ_G0(0); LEDQ_Y1(0); LEDQ_G1(0); LEDB_Y1(1);//宝华路黄灯亮 LEDB_R0(1);//宝华路人行道红灯亮 LEDB_G0(0); LEDB_G1(0); LEDB_R1(0); }else{ //---------------------------------[6,25] LEDALLCLOSE(); //宝田路通行 LEDQ_R1(1);//前进路红灯亮 LEDQ_G0(1);//前进路人行道绿灯亮 LEDQ_R0(0); LEDQ_Y1(0); LEDQ_G1(0); LEDB_G1(1);//宝华路绿灯亮 LEDB_R0(1);//宝华路人行道红灯亮 LEDB_G0(0); LEDB_R1(0); LEDB_Y1(0); } dispaly_xx(25+b); if(count==25+b){ MENU=0;count=0;} if(READKEY3==0){ delay_ms(10); //按键2,切换到MENU=2,设置主干放行时长 if(READKEY3==0) {MENU=3;} } } //MENU==1 if(MENU==2) //--------------------------------------------------------------------------------MENU=2时,延长主干道放行时长 { printf("1rn"); if( READKEY1==0&&a!=0) //按键1,a-- { while( READKEY1==0&&a!=0); a--; } //实现闪烁的效果 In_Urgency(); HC595_display(0,20); delay_ms(200); HC595_display(1,20); delay_ms(200); HC595_display(0,(35+a)/10); delay_ms(200); HC595_display(1,(35+a)%10); delay_ms(200); if(READKEY2==0) { //按键2,a++ while(READKEY2==0); a++; } delay_us(100); if(READKEY3==0) { //按键0,切换到MENU=0 while(READKEY3==0); MENU=0; count=0; } } if(MENU==3) //--------------------------------------------------------------------------------MENU=3时,延长支干道放行时长 { printf("1rn"); if( READKEY1==0&&b!=0) //按键1,b-- { while( READKEY1==0){} b--; } In_Urgency(); //实现闪烁的效果 HC595_display(0,(25+b)/10); delay_ms(200); HC595_display(1,(25+b)%10); delay_ms(200); HC595_display(0,20); delay_ms(200); HC595_display(1,20); delay_ms(200); if(READKEY2==0){ //按键2,b++ while( READKEY2==0){} b++; } if(READKEY3==0){ //按键0,切换到MENU=1 while(READKEY3==0); MENU=1; count=0; } } //*********************************************紧急情况程序 if(MENU==4) { Out_Urgency(); HC595_display(0,0); delay_ms(500); HC595_display(1,0); delay_ms(500); HC595_display(0,20); delay_ms(500); HC595_display(1,20); delay_ms(500); LEDALLOPEN(); } } //while } void In_Urgency(void) { if( READKEY0==0) { while( READKEY0==0){} MENU=4; } } void Out_Urgency(void) { if( READKEY0==0) { delay_ms(10); while( READKEY0==0){} MENU=0; } } void dispaly_xx(u8 num) { HC595_display(0,((num)-count)/10); HC595_display(1,((num)-count)%10); } //定时器3中断服务程序 void TIMx_IRQnHandler(void) //TIM3中断 { if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查TIM3更新中断发生与否 { TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIMx更新中断标志 count++; } } 4.实验总结 (1)主函数设计的思路:把各个功能划分为各个模块单独实现,再设置一个菜单状态变量MENU,用于把各个功能模块串联起来。 当MENU=0时先执行主干道的交通显示,执行完后使MENU=1,跳出该段菜单。 当MENU=1时再执行支干道的交通显示,执行后使MENU=0,跳出该段菜单。 在MENU=0的功能模块中加入按键检测程序,当检测到KEY2时MENU=3,当检测到KEY0时MENU=5。 在MENU=1的功能模块中加入按键检测程序,当检测到KEY2时MENU=4,当检测到KEY0时MENU=5。 当MENU=3时执行主干道放行时间延时程序,用KEY3,KEY4设置加减。 当MENU=4时执行支干道放行时间延时程序,用KEY3,KEY4设置加减。 当MENU=5时执行紧急情况程序。 (2)74HC595驱动芯片总结: HC595是串口转并口的芯片,串口是8位的,也是就HC595一次能同时输出8位二进制,设计程序时一次只能传输8位的变量,若要传输16位或32位变量则要分为2次或4次传输,由芯片手册得到在SCK引脚上升沿时SDI可传输一位数据,程序设计时可先将SCK引脚拉低,用if语句判断8位变量的最高位,若为1则拉高SDI引脚,若为0则拉低SDI引脚,判断后把SCK引脚拉高,形成上升沿,则传输了一位数据,然后8位变量的次高位左移一位在进行新轮的传输,用for语句循环8次,便可传输8位变量,同时HC595芯片内部已经存储满了,若再传输一位就会从Q7’引脚溢出。若是把LCK引脚从低拉高,则8位变量就会从HC595芯片的Q0~Q7引脚输出。 若是要同时输出16位的数据则需要HC595级联如图所示: 级联后当一片HC595存储满后,再传输一位,前一片的最高位就会传输到下一片HC595芯片,当两片HC595都存储满时,LCK引脚从低电平拉成高电平,就可以同时输出16位的二进制数了。 数码管的位选码先传输到U2中,数码管的段选码再传输到U2,此时数码管的位选码会被溢出到U3,此时LCK引脚从低电平拉成高电平,就可点亮数码管。 资料链接: 链接:https://pan.baidu.com/s/1k8gQtofUaEwcVto0nmmIRQ 提取码:sxmh |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1781 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1621 浏览 1 评论
1085 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
728 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1680 浏览 2 评论
1938浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
732浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
570浏览 3评论
596浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
557浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-24 11:08 , Processed in 0.831992 second(s), Total 77, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号