赞
踩
起源
又到了一学期一次的校内电子设计大赛,又到了激动人心的时刻每次电子设计大赛都会出现各种大佬展现他们的作品,对于我这种菜鸟也只能默默观望,但是呢,积极参与还是要有的,记得上一次参加做的基于51的避障小车直接买的套件焊好 然后在烧入程序就直接上战场了(结果自然是成功参与奖)。
这次校内电子设计大赛我选的是多功能台灯制作,由于没有规定单片机的型号,自己选择合适的就行,就想到做一个基于stm32f103c8t6的多功能台灯。自己刚好在自学了一小段时间32了刚好来检测一下自己的学习情况,玩一些基本的外设。
心得总结
说真的看见其他人做的电子设计,就算是比较简单的那种,当自己从头做到尾的时候感受真的不一样,在制作过程中会遇到各种bug,不断的调试查找相关的资料解决后再进行下一步,然后就是反复这样,并没有我们想象的那么简单。但是哈虽然过程艰难了一点最后还是很有成就感的,虽然简单但至少是自己完成的。其实越到后面会发现结果也并没有我们想象的那么重要,其中的过程更能让我们成长,不断发现问题,不断想办法去解决,然后把每一个问题和解决方法做好总结,到最后会发现这些都是我们宝贵的经验。总之呢,虽然我们比其他人笨了一点,技术也并没有他们懂的多,但是我们愿意花更多的时间来弥补这些,成长慢了一点,我始终相信最后我们也都会成为其他人眼中的大佬。
基于stm32f103多功能台灯制作
相关软件链接 下面软件都在这个链接中
链接:https://pan.baidu.com/s/1-1oYhpx1LAaYdCUx36Hg4A
提取码:1ttv
–来自百度网盘超级会员V4的分享
一、环境准备
|Keil5|
|–|–|
| FlyMcu 程序下载软件 |
STC-isp |
|野火串口调式助手
二、硬件准备
| stm32f103C8t6最小系统|
|–|–|
|IIC 四引脚 OLED显示屏|
|光敏传感器|
|蜂鸣器|
|超声波|
|语音模块|
|USB Led灯|
|串口转TTL
|若干杜邦线
|洞洞板
| 按键若干个| |
三、功能构建
四、工程搭建
4.1 选好一个文件目录在下面创建工程文件夹
这里我是基于正点原子标准库模板进行代码的添加的。
4.2 分模块写好相关功能模块
这里的建议是我们每写一个功能的时候都单独的创建一个文件夹然后在里面创建一个xxx.c xxx.h 文件这样写的好处是方便我们的移值也比较清晰的看懂代码模块,特别是代码量很大的时候 这样写的优点就完全体现出来了。
写代码的时候也要把相关的文件路径添加进来哦,要不然是找不到的
4.1 多级菜单显示
把基本的模块函数模块写好了就开始整体功能显示设计了
首先我会把各种功能需要的菜单显示列出来在用oled屏进行显示
1.在开始用多级菜单进行显示之前,也去看了很多其他大佬的博客,自己之前并没有写过这一类的,所以在这第一步就遇到了很多问题。每个菜单界面单独显示的时候很正常,进行页面切换并进行相关功能函数显示的时候就出现了问题,问题的界面切换过来了但是功能并没有进行执行。看了其他博主写的都是创建了结构体和吗,枚举来操作我们界面的切换和函数功能的调用。看了他们的代码才发现真的很菜,不由感慨大佬写的代码就是不一样。
不过最重要的是在后面不断的调试还是根据自己的想法实现了我想要的功能。自然后面也会去多学习一下大佬写代码的风格。
界面展示
主界面
菜单界面
光敏检测界面
语音识别界面
时钟显示界面
整体效果还是不错哈
4.2 主函数逻辑处理及相关函数调用
/************************************多功能台灯********************************
一、相关功能
1.光敏传感器检测光照强度从而来自动调解灯光的暗亮程度
2.通过按键来控制 改变高低电平的占空比调节灯光的暗亮程度
3.通过语音识别来改变灯光的暗亮程度
4.通过超声波来检测 当检测距离大于特定值的关闭灯光,否则在该模式下默认占空比50%
5.通过红外遥控来控制灯光的暗亮程度
6.定时功能 用户给个值 当达到此值时蜂鸣器发出相应的报警提示
二、菜单界面显示
1.光敏界面
2.时钟界面
3.按键界面
4.语音界面
5.超声波界面
*******************************************************************************
Author:xiao yin
Date:2021-11-17
*******************************************************************************/
#include "stm32f10x.h"
#include "usart.h"
#include "oled.h"
#include "infrared.h"
#include "delay.h"
#include "led.h"
#include "adc.h"
#include "ldr.h"
#include "timer.h"
#include "key.h"
#include "timer2.h"
#include "syn6288.h"
#include "buzzer.h"
#include "ultrasonic.h"
#define Min_duty 0 //最小占空比
#define max_duty 100//最大占空比
extern unsigned char sec;//秒
extern unsigned char min; //分
extern unsigned char hour;//时
extern unsigned int count; //计数变量
extern unsigned char time[6]; //存储时间转换后的值
unsigned int adcx; //光敏值 0-100
unsigned char keyvalue;//按键返回值
unsigned char flag;//界面切换标志
unsigned int current_duty = 100; //当前占空比 此时灯光最暗
unsigned int value_duty; //设置占空比的值
unsigned char flag_function = 0;//函数功能标志位
unsigned char RxData; //语音接收
unsigned int Time = 120;//定时时间变量
float dis; //接收超声波返回的数据
void main_interface(void);
void menu_interface(void);
void Interface1(void);
void Interface2(void);
void Interface3(void);
void Interface4(void);
void Interface5(void);
void Ldr_Tackle(void);
void Time_Display(void);
void KEY_Tackle_Puty(void);
void Voice_Tackle(void);
/*********************************************三个界面显示函数*****************************/
//主页面
void main_interface(void)
{
// OLED_Clear(0);
// delay_ms(10);
OLED_ShowCHinese(6,0,0);//智
OLED_ShowCHinese(26,0,1);//能
OLED_ShowCHinese(46,0,2);//台
OLED_ShowCHinese(66,0,3);//灯
OLED_ShowCHinese(86,0,4);//系
OLED_ShowCHinese(106,0,5);//统
OLED_ShowNum(6,4,2021,4,16);
OLED_ShowCHinese_TWO(40,4,0);//年
OLED_ShowNum(60,4,11,2,16);
OLED_ShowCHinese_TWO(74,4,1);//月
OLED_ShowNum(92,4,17,2,16);
OLED_ShowCHinese_TWO(108,4,2);//日
}
//菜单页面
void menu_interface(void)
{
// OLED_Clear(0);
// delay_ms(10);
//
OLED_ShowString(20,0,(unsigned char *)"Function",8);
OLED_ShowString(20,2,(unsigned char *)"1.Light Test",8);
OLED_ShowString(20,4,(unsigned char *)"2.Time Clock",8);
OLED_ShowString(20,6,(unsigned char *)"3.KEY Test",8);
}
//光敏功能界面1
void Interface1(void)
{
// OLED_Clear(0);
// delay_ms(10);
//
OLED_ShowString(20,0,(unsigned char *)"Light Test",8);
OLED_ShowString(10,3,(unsigned char *)"VALUE:",8);
OLED_ShowString(10,5,(unsigned char *)"DUTY :",8);
OLED_ShowString(10,7,(unsigned char *)"MODE :",8);
OLED_ShowNum(60,3,adcx/100,2,4);
OLED_ShowNum(68,3,adcx/10%10,2,4);
OLED_ShowNum(76,3,adcx%10,2,4);
OLED_ShowNum(60,5,(100-current_duty)/100,2,4); //百位
OLED_ShowNum(68,5,(100-current_duty)/10%10,2,4);//十位
OLED_ShowNum(76,5,(100-current_duty)%10,2,4);//个位
OLED_ShowNum(60,7,1,2,4);//mode
}
//时钟功能界面2
void Interface2(void)
{
//界面清屏
// OLED_Clear(0);
// delay_ms(10);
//刷新重新要显示的数据
OLED_ShowString(26,1,(unsigned char *)"Time Clock",8);
OLED_ShowString(30,5,(unsigned char *)"MODE :",8);
}
//按键功能界面3
void Interface3(void)
{
//界面清屏
// OLED_Clear(0);
// delay_ms(10);
//刷新重新要显示的数据
OLED_ShowString(40,0,(unsigned char *)"KEY",8);
OLED_ShowString(10,3,(unsigned char *)"DUTY :",8);
OLED_ShowString(10,5,(unsigned char *)"MODE :",8);
OLED_ShowNum(68,3,(100-current_duty)/100,2,4); //百位
OLED_ShowNum(76,3,(100-current_duty)/10%10,2,4);//十位
OLED_ShowNum(84,3,(100-current_duty)%10,2,4);//个位
OLED_ShowNum(68,5,3,2,4);//mode
}
/*****************************************************************************************/
//功能界面四 语音模式
void Interface4(void)
{
OLED_ShowString(20,0,(unsigned char *)"Voice Test",8);
OLED_ShowString(10,3,(unsigned char *)"DUTY :",8);
OLED_ShowString(10,5,(unsigned char *)"MODE :",8);
OLED_ShowNum(60,3,(100-current_duty)/100,2,4); //百位
OLED_ShowNum(68,3,(100-current_duty)/10%10,2,4);//十位
OLED_ShowNum(76,3,(100-current_duty)%10,2,4);//个位
OLED_ShowNum(60,5,4,2,4);//mode
}
//超声波测距界面
void Interface5(void)
{
OLED_ShowString(20,0,(unsigned char *)"CSB Test",8);
OLED_ShowString(10,4,(unsigned char *)"DIS:",8);
OLED_ShowString(10,6,(unsigned char *)"DUTY :",8);
OLED_ShowNum(60,4,(int)dis/100,2,4); //百位
OLED_ShowNum(68,4,(int)dis/10%10,2,4);//十位
OLED_ShowNum(76,4,(int)dis%10,2,4);//个位
OLED_ShowNum(60,6,(100-current_duty)/100,2,4); //百位
OLED_ShowNum(68,6,(100-current_duty)/10%10,2,4);//十位
OLED_ShowNum(76,6,(100-current_duty)%10,2,4);//个位
}
/*********************************************功能函数*********************************/
//光敏电阻改变led灯的亮度
void Ldr_Tackle(void)
{
adcx = Lsens_Get_Val();
if(adcx <=30 )
{
current_duty = 10;
}
else if(adcx > 30 && adcx <= 50)
{
current_duty = 40;
}
else if(adcx >50 && adcx <=70)
{
current_duty = 60;
}
else if(adcx>70 && adcx <= 90)
{
current_duty = 80;
}
else{
current_duty = 0;
}
// TIM_SetCompare2(TIM3,current_duty);
//printf("光线强度为:%d\n",adcx);
//printf("占空比为:%d\n",100-current_duty);
}
//对时间进行显示
void Time_Display(void)
{
unsigned char i;
OLED_ShowNum(30,3,time[0],2,4);
OLED_ShowNum(38,3,time[1],2,4);
OLED_ShowChar(46,3,':',4);
OLED_ShowNum(52,3,time[2],2,4);
OLED_ShowNum(60,3,time[3],2,4);
OLED_ShowChar(68,3,':',4);
OLED_ShowNum(74,3,time[4],2,4);
OLED_ShowNum(82,3,time[5],2,4);
OLED_ShowNum(74,5,2,2,4);//mode
//如果超过
if(sec >= Time)
{
for(i =0; i< 4;i++)
{
Buzzer_On();
delay_ms(500);
Buzzer_Off();
}
sec = 0;
}
}
//按键处理函数通过key2 key3两个按键来控制灯光的占空比
//key 2进行占空比的累加 key3 进行占空比的减
void KEY_Tackle_Puty(void)
{
keyvalue = 0;
keyvalue = KEY_Scan();
//当占空比加到最大值的时候重新从最小的占空比开始 当占空比减到最小值的时候重新从最大值开始
if(keyvalue == 3 )//为1的时候进行占空比加
{
current_duty+=20;
if(current_duty >=max_duty )
{
current_duty = 0;
}
}
if(keyvalue == 4)
{
current_duty-=20;
if(current_duty <= Min_duty)
{
current_duty = 100;
}
}
//printf("keyvalue = %d\n",keyvalue);
}
//超声波处理函数
void Csb_Tackle(void)
{
dis = Senor_Using();
printf("current dis = %.2f\n",dis);
if(dis >= 500)
{
Buzzer_On();
delay_ms(500);
Buzzer_Off();
current_duty = 100; //检测不到物体关闭灯光
}
else
{
current_duty = 50; //检测到时候 默认 一半
}
}
//语音功能处理
void Voice_Tackle(void)
{
if(RxData == '0')
{
Buzzer_On();
delay_ms(500);
Buzzer_Off();
current_duty = 100; //关闭
}
else if(RxData == '1')
{
current_duty = 20;
//printf("rec 1 success\n");
}
else if(RxData == '2')
{
current_duty = 50;
// printf("res 2 success\n");
}
else if(RxData == '3')
{
current_duty = 90;
//printf("re3 success\n");
}
else if(RxData == '4')
{
Time = 10;
//printf("re 4 success\n");
}
else if(RxData == '5')
{
Time = 20;
//printf("re 5 success\n");
}
else if(RxData == '6')
{
Time = 30;
//printf("re 6 success\n");
}
else {
//printf("cmd is error\n");
}
}
/**********************************************************************************************/
//通过按键来进行界面的切换
unsigned char Key_Mode(void)
{
// delay_ms(500);
keyvalue = KEY_Scan(); //按键1来进行模式的切换
if(keyvalue == 1) //判断按键1是否被按下
{
flag++;
}
if(keyvalue == 2)
{
flag--;
}
switch(flag)
{
case 1:OLED_Clear(0);main_interface();break;
case 2:OLED_Clear(0);menu_interface();break;
case 3:OLED_Clear(0);Interface1();flag_function=1;break;
case 4:OLED_Clear(0);Interface4();flag_function=2;break;
case 5:OLED_Clear(0);Interface2();flag_function=3;break;
case 6:OLED_Clear(0);Interface5();flag_function=4;break;
case 7:OLED_Clear(0);Interface3();flag_function=5;break;
default:break;
}
return flag_function; //返回功能函数的标志位
}
/*****************************************主函数*********************************/
int main(void)
{
unsigned char value =0;
Infrared_GPIO_INIT();
KEY_GPIO_INIT();//按键初始化
USART_INIT(9600); //串口初始化
LED_GPIO_INIT();// led初始化
CH_SR04_Init(); //超声波初始化
Buzzer_GPIO_Init();//蜂鸣器初始化
Lsens_Init(); //光敏传感器初始化
TIM3_PWM_Init(100-1,7200-1);//pwm控制初始化 1hkz 计数到100为10ms
OLED_Init(); //初始化OLED
OLED_Clear(0);
while(1)
{
value = Key_Mode();
if(value == 1)
{
Ldr_Tackle(); //光敏模式处理
}
else if(value == 2)
{
Voice_Tackle(); //语音模式功能处理
}
else if(value == 3)
{
Time_Display(); //定时模式处理
}
else if(value == 4)
{
Csb_Tackle(); //超声波功能处理
}
else if(value == 5)
{
KEY_Tackle_Puty(); //按键模式功能处理
}
TIM_SetCompare2(TIM3,current_duty);
}
}
/***********************************串口中断****************************/
//通过语音发送串口接收数据来进行灯光占空比的节和定时长短 这里我写的比较简单 要实现其他功能
//大家自己修改一下即可
void USART1_IRQHandler(void){
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
RxData=USART_ReceiveData(USART1);
if(RxData == '0')
{
Time = 20;
Buzzer_On();
delay_ms(50);
Buzzer_Off();
}
else if( RxData == '1')
{
current_duty = 10;
Buzzer_On();
delay_ms(50);
Buzzer_Off();
}
else if(RxData == '2')
{
current_duty = 50;
Buzzer_On();
delay_ms(50);
Buzzer_Off();
// printf("res 2 success\n");
}
else if(RxData == '3')
{
current_duty = 90;
Buzzer_On();
delay_ms(50);
Buzzer_Off();
//printf("re3 success\n");
}
else if(RxData == '4')
{
Time = 10;
Buzzer_On();
delay_ms(50);
Buzzer_Off();
//printf("re 4 success\n");
}
else if(RxData == '5') //关闭灯光
{
current_duty =100;
Buzzer_On();
delay_ms(50);
Buzzer_Off();
//printf("re 5 success\n");
}
else if(RxData == '6')
{
Time = 30;
Buzzer_On();
delay_ms(50);
Buzzer_Off();
//printf("re 6 success\n");
}
else {
//printf("cmd is error\n");
}
USART_SendData(USART1,RxData);
}
}
整体实物(太丑了 ^ ^)
上面代码实测功能可以实现,当然在逻辑处理上还是有有多问题 后面我会慢慢优化,上面纯属个人理解有错还希望各位大佬指正。学习一步一个脚印慢慢来,时间会见证一切 加油鸭。
最后工程源码的链接我放这里了有需要的小伙伴自取
有问题大家一起讨论 共同进步
链接:https://pan.baidu.com/s/11gRoBYrJTWg69tV65VzX5w
提取码:jyep
–来自百度网盘超级会员V4的分享
现在项目不开源了哦,有需可私 创作不易拒绝白嫖
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。