一、开发环境介绍

主控芯片:  正点原子STM32F103ZET6精英开发板

oled:中景园七针脚0.96寸oled

代码编程软件: keil5

代码下载地址: stm32流水灯项目

希望大家仔细看一看是否符合自己的需求,实际上本文中写到的很多东西已经能为课设所用,理清逻辑后自己编程也很方便的,但如果想直接copy我的项目则需要购买板子、oled、项目文件(或许也可以直接proteus仿真,但本人未做尝试),总之请仔细斟酌再做打算。

二、项目要求

流水灯的设计:
芯片:LPC2000系列或者STM32,建议大家用STM32
基础部分:
(1)利用P0口的四个引脚控制四个发光二极管,第一个灯亮过2秒之后,延时2秒,第二个亮,以此类推,当第四个亮过之后就让四个二极管全亮,保持2秒,然后不断循环。
(2)利用Keil uVision4软件作为交叉编译环境。
(3)利用Proteus 8 Professional 软件作为程序的仿真测试。

提高部分:
(1)利用P0口的一个管脚作为一个按键信号输入,其作用是启动流水灯的开始和停止。(第一次按启动,第二次停止,第三次启动,以此类推)
(2)利用P0口的一个管脚作为一个按键信号输入,其作用是设置灯亮的时间,分三档1秒,2秒,3秒(第一次按1,第二次2秒,第三次3秒,第四次1秒,以此类推)
(3)基于uc/os-II操作系统,完成以上程序设计。

整个任务分为四个工作阶段:
1.安装开发环境,熟悉开发环境的基本操作。(开发环境的功能掌握)
2.查阅相关资料,编制程序代码。(程序的流程图)
3.调试相关程序,在调试过程中,修改相关程序。(调试过程中的问题)
4.对整个设计过程分析总结,提交设计报告。(总的设计报告)

作业包括:
第一个(1、2、3)操作报告(2页纸正反面);
第二个总的设计报告;
第三个程序打包(工程源文件打包)
第四个仿真程序(若有实物,直接视频更好,鼓励采用实物方式,但不是必须)

课程设计提交形式  :
电子版:
1、2、3操作报告(合计3页)、 总的设计报告、程序打包(工程源文件)、仿真程序(若有实物,直接视频更好,鼓励采用实物方式,但不是必须)、仿真程序或者实物实际运行讲解视频(这个必须有)、自己对自己报告完成情况评价,并讲明自己课设内容的优缺点(优、良、中、及格、不及格)。

报告格式:学号 姓名 班级  
总的设计报告要求:
题目(加粗四号居中宋体)
班级  姓名  学号(加粗四号居中宋体)
1、流水灯的设计原理。(小四宋体)
2、程序流程图及代码分析。(小四宋体)
3、设计结果分析及改进之处。(小四宋体)
4、设计体会。(小四宋体)

三、实际实现效果

(1)、能够实现流水灯效果,但只有两个LED,如果想要华丽的效果可以尝试网上购买LED

(2)、通过控制定时器的打开与关闭,能够实现流水灯暂停/启动效果

(3)、通过外部中断程序设置定时器自动重装载初值,能够完成流水灯闪烁时间档位的切换(第一次按1,第二次2秒,第三次3秒,第四次1秒)

(4)、通过开启pvd掉电检测,能够实现简单的掉电数据保存,在检测到电压低于2.9v时,会进入掉电中断函数,将重要信息写入flash,并在重新上电后读出flash数据并初始化。

(5)、每次按下按键都会有蜂鸣器响,并且在oled上提示相关信息。

(6)、基于uc/os-II操作系统的移植没有做!!!!!!

四、核心代码

4.1 LED流水灯

该部分通过extern关键字引用了全局变量led_flag,并根据这个变量进行led展示

void LED_show()
{led_flag==6 ? led_flag=1:led_flag++;//六次一循环if(led_flag==1){LED0=0;LED1=1;}else if(led_flag==3){LED0=1;LED1=0;}else if(led_flag==5){LED0=0;LED1=0;}else{LED0=1;LED1=1;}
}

4.2 定时器

需要注意的是调用初始化定时器函数后还需要一个    TIM3->CR1|=0x01; 语句来使能定时器 3,这样才开始自动重装载计时。实际上,这句代码通常是在定时器初始化函数中的,但为了更好地实现其他功能,故而提取出来。

void TIM3_IRQHandler(void)
{ if(TIM3->SR&0X0001) //溢出中断{LED_show();} TIM3->SR&=~(1<<0); //清除中断标志位
}
//通用定时器 3 中断初始化
//这里时钟选择为 APB1 的 2 倍,而 APB1 为 36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器 3!
void TIM3_Int_Init(u16 arr,u16 psc)
{RCC->APB1ENR|=1<<1; //TIM3 时钟使能 TIM3->ARR=arr; //设定计数器自动重装值//刚好 1ms TIM3->PSC=psc; //预分频器 7200,得到 10Khz 的计数时钟 TIM3->DIER|=1<<0; //允许更新中断 //TIM3->CR1|=0x01; //使能定时器 3TIM3->EGR|=1<<0;        //产生更新事件(这两句话是正点原子stm32相关bug,如不加,初始化后立刻进入中断)TIM3->SR=0;             //清所有标志MY_NVIC_Init(2,3,TIM3_IRQn,2);//抢占 2,子优先级 3,组 2 }
}

4.3 pvd掉电检测并保存数据

开启pvd掉电检测,设置阈值为2.9v,当掉电后电压低于2.9v时触发中断,进行数据保存

void PWR_PVD_Init(void)
{      RCC->APB1ENR|=1<<28;    //使能PORTB时钟PWR->CR |= 7<<5; //2.9V 电压阀值PWR->CR |= 1<<4; //PVD使能   EXTI->IMR|=1<<16;//EXTI->FTSR|=1<<16;//这里写错了 这样写进入不了中断,注意上升沿和下降沿产生的中断刚好是翻过来的,这里感觉是资料翻译错误的原因造成的//改为下面这样就正常了EXTI->RTSR|=1<<16;//配置这个寄存器才是断电瞬间保存数据EXTI->EMR |=1<<16;EXTI->SWIER |= 1<<16;MY_NVIC_Init(0,0,PVD_IRQn,2);//组2,最低优先级
}
void PVD_IRQHandler(void)
{EXTI->PR |=1<<16;//清中断  if (((PWR->CSR)&(1<<2))!=0)//当电压低于阈值{u16 msg[2];msg[0]=led_flag;msg[1]=time_gear;STMFLASH_Write(FLASH_SAVE_ADDR,msg,2);
//                  OLED_ShowString(8,16,"OK",16,1);//经过测试,掉电中断确实执行,但是可能数据写入速度不够                                                               }
}

4.4 外部中断(换挡、暂停/启动、掉电保存模式)

//外部中断 0 服务程序
//函数功能,进入掉电模式
void EXTI0_IRQHandler(void)
{
delay_ms(10); //消抖
if(WK_UP==1) //WK_UP 按键
{BEEP=1;OLED_Clear();PWR_PVD_Init();OLED_ShowString(8,0,"save mode",16,1);BEEP=0;
}
EXTI->PR=1<<0; //清除 LINE0 上的中断标志位
}
//外部中断 3 服务程序
//函数功能,暂停,开启流水灯
void EXTI3_IRQHandler(void)
{delay_ms(10); //消抖if(KEY1==0) {BEEP=1;led_on=!led_on;if(led_on==1){TIM2->CR1 |= (0x01);TIM3->CR1 |= (0x01);OLED_Clear();OLED_ShowString(8,16,"Turn on",16,1); }else{TIM2->CR1 &= ~(0x01);//TIM3 时钟使能 TIM3->CR1 &= ~(0x01);OLED_Clear();OLED_ShowString(8,16,"Turn off",16,1);}}BEEP=0;EXTI->PR=1<<3; //清除 LINE3 上的中断标志位
}
//外部中断 4 服务程序
//函数功能:档位切换
void EXTI4_IRQHandler(void)
{delay_ms(10); //消抖if(KEY0==0) //按键 KEY0{BEEP=1;time_gear++;//档位切换time_gear%=3;OLED_Clear();OLED_ShowString(8,0,"Gear changed!",16,1);sprintf(OLED_ShowBuff,"Gear: %d",time_gear);OLED_ShowString(8,48,OLED_ShowBuff,16,1); TIM2->CR1&=~(0x01); TIM3->CR1&=~(0x01); //先关闭定时器3中断TIM2->SR&=~(1<<0);TIM3->SR&=~(1<<0); //清除中断标志位,从而可以快速切换if(time_gear>=1){//进行了档位切换,且由低档变为高档TIM2_Int_Init((time_init[time_gear]-TIM3->CNT),7199);//根据当前按下按键次数进行定时器的初始化 }else{if(TIM3->CNT>=9999){//3档由29999记到0,如果小于19999需要立马进入中断TIM2_Int_Init(50,7199);//给予定时器2一个很小的记数值,计时满立刻进行LED状态翻转}else {TIM2_Int_Init((time_init[time_gear]-TIM3->CNT),7199);//根据当前按下按键次数进行定时器的初始化}}if(led_on==1)  {TIM2->CR1 |= (0x01);TIM3->CR1 |= (0x01);}else {TIM2->CR1&=~(0x01); TIM3->CR1&=~(0x01); }            }BEEP=0;EXTI->PR=1<<4; //清除 LINE4 上的中断标志位
}

 4.5 主函数

主函数首先进行相关外设初始化,而后读取flash数据,若读取正确数据则根据数据进行复位流水灯,否则进行零状态初始化。需要注意的是,读取flash数据后需要进行擦除,否则pvd掉电的短暂时间难以写入数据,从而造成保存数据失败。

int main(void)
{ u16 datatemp[2]={0,0};//接收上次掉电保存的数据u16 i=0;//用于flash数据擦除u16 secremain=1024-(FLASH_SAVE_ADDR%2048)/2;u32 offaddr=FLASH_SAVE_ADDR-STM32_FLASH_BASE;u32 secpos=offaddr/2048;Stm32_Clock_Init(9); //系统时钟设置uart_init(72,115200); //串口初始化为 115200delay_init(72); //延时初始化OLED_Init();//OLED初始化BEEP_Init();//蜂鸣器初始化EXTIX_Init();//外部中断初始化LED_Init(); //初始化与 LED 连接的硬件接口//相关信息展示OLED_ShowString(8,0,"init OK!",16,1);OLED_ShowString(8,16,"Turn on",16,1);STMFLASH_Read(FLASH_SAVE_ADDR,datatemp,2);//原来此处是SIZEif(datatemp[1]==0||datatemp[1]==1||datatemp[1]==2){led_flag=datatemp[0]-1;  time_gear=datatemp[1];}else{//flash没有正确数据,直接初始化led_flag=0; time_gear=0;}sprintf(OLED_ShowBuff,"LED: %d",led_flag);OLED_ShowString(8,32,OLED_ShowBuff,16,1); sprintf(OLED_ShowBuff,"Gear: %d",time_gear);OLED_ShowString(8,48,OLED_ShowBuff,16,1); //擦除flash数据,否则掉电时间内难以写入STMFLASH_Unlock(); //解锁       if(i++<2)STMFLASH_ErasePage(secpos*2048+STM32_FLASH_BASE);//擦除这个扇区STMFLASH_Lock();//上锁//根据掉电储存信息进行复位LED_show();//LED展示TIM3_Int_Init(time_init[time_gear],7199); //定时器初始化TIM3->CR1|=0x01; //使能定时器 3    while(1);
}

五、效果演示

5.1 初始化

初始化时,会从flash读数据,如果读出正确数据,则会根据数据进行初始化,否则进行零状态初始化,并且在oled上显示相关信息。

5.2 暂停、启动

实现流水灯的暂停、启动功能,并且会在oled上显示Turn on/Turn off信息。

5.3 换挡

能够实现流水灯闪烁时间档位切换,当Gear=0时,流水灯变换时间为1s,Gear=2时,流水灯变换时间位2s。

 5.4 数据保存模式

按下Key_up键,进入数据保存模式,当设备掉电后,会自动读取led的状态以及时间档位并且存储到flash,以供重新上电时复位。

 5.5 保存后重新上电

进入保存模式后掉电再上电,会根据flash信息重新初始化,重新上电时,会从上次闪烁的LED开始亮,比如上次掉电时是两个灯一起亮,这次上电则是从两个灯一起亮开始;上次掉电时,闪烁频率位2s一次变换,则重新上电也是2s一次。若不进入保存模式,发生掉电再上电只会进入零状态初始化。

基于stm32的流水灯实现相关推荐

  1. 基于STM32单片机流水灯仿真与程序设计

    STM32单片机流水灯仿真与程序设计 摘要 本次程序设计和仿真是基于Proteus和keil的环境对STM32F103系列单片机进行流水灯设计,通过配置STM32的GPIO工作模式,实现LED的点亮和 ...

  2. 智能灯控制页面用HTML编写,一种基于STM32的智能灯控制系统的制作方法

    本发明涉及电子系统控制领域,具体是一种基于STM32的智能灯控制系统. 背景技术: 随着我国教育业的发展,学校照明用电量急速增加,电能损失也呈现出增大的趋势.目前,国内外照明自动控制装置基本都采用被动 ...

  3. multisim13学习_基于Multisim13数字流水灯电路设计与仿真 - 镇江高专学报.PDF

    基于Multisim13数字流水灯电路设计与仿真 - 镇江高专学报 第30卷第1期 镇 江 高 专 学 报 Vol.30 No.1 2017年1月 JournalofZhenjiangCollege ...

  4. 基于STM32F103C8T6实现流水灯的操作实验

    一.GPIO端口的初始化 1.配置时钟 1.找到时钟使能寄存器映射基地址即复位时钟控制 由于本次实验采用GPIOA.B.C三个端口,该三个端口又都属于APB2总线. 2.找到APB2总线端口偏移地址以 ...

  5. 【原创】基于ARM的流水灯仿真示例

    本设计使用的仿真工具是Proteus 7.4,IDE是ADS 1.2,芯片是LPC2134 在Proteus中的电路图如下图所示: 本设计使用的是周立功的LPC2131的工程模板.LPC2131的RA ...

  6. VHDL||数字系统设计实验--基于VHDL的流水灯电路设计

    实验目的: 学习设计一个流水灯电路,并在实验板验证. 学习简单时序电路的设计和硬件测试. 学习使用VHDL语言方法进行逻辑设计输入. 实验内容: 实验VHDL程序: LIBRARY IEEE; USE ...

  7. 基于STM32震动感应灯

    元器件:1.震动感应器,继电器,LED灯等. 震动传感器:引脚VVC.GND.高低点位变化DO(接STM32的信号端).AO模拟信号端(本实验未使用到) 其中实现的代码如下: void Shake_I ...

  8. 基于Nios-II的流水灯实验

    文章目录 一.实验内容 二.实验原理 三.实验步骤 3.1.硬件部分 3.2.软件部分 3.3.运行结果 一.实验内容 二.实验原理 控制 LED 灯闪烁的用户程序代码很小,将其固化在片内 ROM 来 ...

  9. 基于51单片机的八位流水灯(三种形式)

    写一下寒假做的51小项目. 基本项目 基于AT89C51的流水灯:流水灯共八个,可以实现交替闪烁,一起闪烁,左右流水灯等效果. 模式一:按动key1,实现1,3,5,7和2,4,6,8交替闪烁: 模式 ...

最新文章

  1. Struts2 2.5版本新配置filter-class
  2. jquery.validate不用submit而用js提交的例子
  3. Scala花括号和圆括号的区别
  4. 一招让你彻底掌握C语言中运用宏以及#与##的妙用
  5. mysql重新载入my.cnf_怎么重新加载MySQL的my.cnf?
  6. 华为高管涉嫌受贿已被带走调查
  7. 系统安装无法找寻硬盘!!!【全系列】
  8. 第二章例题:EnvironmentVars
  9. 省市区三级联动菜单(附数据库)
  10. 汇总Eclipse快捷键
  11. 海蜘蛛理由器做端口映射
  12. freeradius mysql_centos7 freeradius mysql配置
  13. Taro项目中设置了设计稿尺寸
  14. 数据分析报告编写规范
  15. 计算机科学家与科学之路----2000年图灵奖得主美籍华人姚期智院士特邀报告
  16. php去除头尾空格,php去除头尾空格的2种方法,php头尾空格2种_PHP教程
  17. 怎么将图片进行圆角处理?
  18. 关于自建ip池可能出现的问题
  19. 解决ie11下antd-vue input的clear点击无效
  20. 数据治理建设管理办法(参考)(粉丝福利)

热门文章

  1. 【Java中的UUID是什么?】
  2. php 合并重复数据合并,PHP_php合并数组中相同元素的方法,本文实例讲述了php合并数组中 - phpStudy...
  3. python机器人助手--丫丫1.0版本(基于百度语音和图灵机器人)
  4. ElasticSearch查询语法
  5. Excel如何查找批注
  6. 基于SSM的数码商城的设计与实现【课程设计】
  7. 远程服务器如何创建分支,Git 创建分支提交远程分支详解
  8. 银行卡又入账1579元,我错怪老东家了
  9. 组播ip mac转换 c语言,组播IP地址与组播MAC地址之间的换算方法与例子
  10. 多级菜单库及菜单代码生成器