关于嵌入式校内实习作评的3/4作品展示(电子智能手表)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言。

 作品是基于STM32F411CUE6芯片,制作的一个智能手表的项目。目前整个项目用到了ADC按键,按键中断,五个定时器,分别对应呼吸灯的输出,马达的输出,三个定时中断。


一、开机界面的描述

在这里插入图片描述
 视频拍的不好,动图效果就更差,只能画一个这样的图来说明。

1.最左面三个中文汉字的显示

2.横杠,横杠,大于号的功能描述和实现方法

 第二行方格除了第一排汉字以外的三个图形,我实现的效果是第一秒第一个横杠出现,第二秒第一个横杆消失,第二个横杠出现,以此类推,到最后面就从头再来。
 关于部分的实现方式是通过一个一秒定时器,对OLED屏幕对应的地方擦除,写入。
代码部分:

		switch(c)
		{
			case 0 : 	oled_dis_str24(2,16,"-"); c++; break;
			case 1 : 	OLED_clear_START_1(); c++; break;
			case 2 : 	oled_dis_str24(2,32,"-"); c++; break;
			case 3 : 	OLED_clear_START_2(); c++; break;
			case 4 : 	oled_dis_str24(2,48,">"); c++; break;
			case 5 : 	OLED_clear_START_3(); c++; break;
			case 6 : 	c=0; break;
		}

特别需要注意的是,因为中断函数其实也是单片机不断运行的一个局部函数,那么这个如果要实现C++变量正常加减并且不卡主函数运行的功能需要对变量C修饰静态变量,还是不明白请移步局部静态变量相关知识。

3.进度条的描述和实现

 进度条没什么描述的,我就直接说一些实现遇到的难处和方法。首先进度条是需要自己掌握开机时间的,因为这个项目的开机其实是一个主函数延时产生的一个假开机,所以,进度条的时间需要自己把握。我通过串口的时间戳来把握了进度条的时间问题。
 还有一个难处就是没有合适的时间中断来让他1%的加载,所以需要占用一个额外的定时器来实现这个功能
代码部分

	void TIM1_UP_TIM10_IRQHandler(void)
{	
	static int load;
	if(TIM10->SR & (1<<0))
	{
		TIM10->SR &= ~(1<<0);
		//紧急事件
		if(flag_time_10 ==1)	
	{	
		oled_dis_pic(6,4+load,16,3,load_p);
		load = load+4;
	}
}

关于代码的解释: flag_time是为了节省定时器而用的,不希望这个定时器只有开机的时候才能用,而且这个开机的功能只在开机的时候才用到,所以自己制作一个标志位,让它只在开机的时候用这个功能。
 oled_dis_pic是一个封装好的oled屏幕传递函数,第一个参数是页数,第二个参数是行数,第四个和第五个参数是图片的长和宽,最后一个参数是图片数据数组的一个地址(这里的图片便是涂黑三行)。这个函数实现的功能就是定时器第一次进入中断,从第四行开始涂黑三行,第二次进入中断,从第八行开始涂黑三行。

4.动图的实现

 因为上面的的功能都是用定时器中断进入的,那么动图的实现就用主函数的for函数和延时函数来卡住它实现
代码部分:

	for(j=0 ;j<1;j++)
   {
	  int i =0;//不可改动,图片帧数
			for(i = 0;i < 7;i++)
		{	
			oled_dis_pic(0,64,64,64,pic[i]);
			delay(50);
		}
	}

5.关于电动机的转动和PWM呼吸灯的实现

 电机的转动需要一个定时器的PWM功能,灯也需要一个,但是如果需要实现呼吸灯的话,在不卡主函数的情况下,就格外需要一个定时器加入进来改变CCR寄存器的值。
代码部分:

	if(flag_time_1 == 1)
	{
		if(j<1000)
		{
		i+=10;
		j+=10;
		TIM3->CCR2 = i;
		//printf("%d  %d\r\n",i,j);
		}
		else 
		{
			i-=10;
			TIM3->CCR2 = i;
			j+=10;
			//printf("%d  %d\r\n",i,j);
		}	
		if(j>=2000)
		{
			j=0;
		}
	}

二、界面一:时间显示的实现

1.RTC:real time clock(真实时间时钟)

 关于RTC使用等信息,本文不多赘述。主要只介绍在主函数中可以通过更新时间寄存器来不断的使定时器中断响应读取STM32内RTC信息的方法。这种方法可以使整个系统的运行更为流畅。非常推荐。

三、界面二:灯相关的控制功能

在这里插入图片描述 先说实现的功能,进入该页面后,指示部分会闪烁。我们用到的按键是通过ADC检测的五方向按钮(具体实现功能在本文中不过多赘述),五个方向分别为上下左右和中间。当刚进入页面的时候,按上或者下都会移动指示部分,在灯亮度和灯速度之间来回切换(灯速度指呼吸灯的速度)。在指示部分指向灯速度或者灯亮度的时候,按下中间,便会分别进入各自的<0>部分,也就是循环内闪烁部分。进入这个部分时,0会闪烁表示可以按左右进行选择灯的亮度或者呼吸灯的速度,于此同时动图会根据目前的灯亮度的情况进行切换。

1.指示部分

 指示部分在这个页面是用一个定时器完成成,因为没有定时器符合它的工作时间,比如动图的工作时间必须在人眼识别不到的情况下,而指示部闪的太快会可能会导致看不见或者没那么舒服,所以我这里用了一个独立的定时器完成这个工作。
 工作的实现是通过指定位置的擦除和指定位置的写入实现的
代码部分

		if(flag_time_9 == 2)
	{
		static uint8_t count_9_2 = 0;
		if(count_9_2 == 0)
		{
			count_9_2++;
			if(flag_time_9_2_set==0)
			{
				oled_dis_16(0,48,"<");
			}
			else if(flag_time_9_2_set==1)
			{
				oled_dis_16(4,48,"<");
			}
		}

2.闪烁内循环部分

 该部分借鉴的是C++的一个登陆系统,是B站的一个黑马程序员教的。为了让按键总体的左右功能用于控制0变成1的功能而不会翻译的功能,就需要实现这个功能的时候不走主函数的查询循环,而是走我实现这样的功能的一个小循环。(当然如果整个代码的主框架不一样,也许不需要用这种方式,代码只有更好没有最好。)
 实现部分是通过中间按键的中断进入的,只要程序目前是在这个页面,并且接收都中间按键的中断,便进入相应的while循环里面。
代码实现:

中断函数部分:
		if((interrupt_2_set==1)&&(flag_time_9_2_set==0)) //灯亮度
		{
			flash_2 = 1;
		}
		if((interrupt_2_set==1)&&(flag_time_9_2_set==1)) //灯速度
		{
			flash_2 = 2;
		}
	}
	主函数部分:
		//闪烁和控制
	if(flash_2 == 1)
	{
		while(1)
		{
		key_2 = get_KEY_number();
		if(key_2==1)
		{
			break;
		}
		else if(key_2==2)
		{
			break;
		}
		else if(key_2==3)
		{
			show--;
		}
		else if(key_2==4)
		{
			show++;
		}
		if(show>4)
		{
			show = 0;
		}
		OLED_clear_2_1_flash();
		delay(100);
		//闪烁多少
		show_page_2_1(show);
		set_light(show);
		delay(100);
		}
		TIM3->CCR2= 0;
	}
	else if(flash_2 == 2)
	{
		while(1)
		{
		key_2 = get_KEY_number();
		if(key_2==1)
		{
			break;
		}
		else if(key_2==2)
		{
			break;
		}
		else if(key_2==3)
		{
			show--;
		}
		else if(key_2==4)
		{
			show++;
		}
		if(show>4)
		{
			show = 0;
		}
			OLED_clear_2_2_flash();
			delay(100);
			show_page_2_2(show);
			flag_time_1 = 1;
			set_speed(show);
			delay(100);
		}
		flag_time_1 = 0;
		TIM3->CCR2= 0;
	}
	flash_2 = 0;
	delay(100);
}

相关的函数和自己设计的标志位,建议通过整个工程查看。

3.动图部分

 动图部分设置相应的标志位,检查整个程序运行的程度,通过标志位来让图显示即可,如果显示的不是动图也就不需要启用一个定时器来让图动起来
代码部分:

主函数在上面参考
调用函数:
void set_speed_pic(uint8_t light)
{
		switch(light)
		{
			case 0 : 	delay_TIM10_IT_Init(100); break;
			case 1 : 	delay_TIM10_IT_Init(50); break;
			case 2 : 	delay_TIM10_IT_Init(25); break;
			case 3 : 	delay_TIM10_IT_Init(17); break;
			case 4 : 	delay_TIM10_IT_Init(10); break;
		}
}
中断函数:
		if(flag_time_10 == 2)	
	{
		static uint8_t TIM10_2_1 = 0;
		TIM10_2_1++;
		oled_dis_pic(0,64,64,64,pic[TIM10_2_1]);
		
		if(TIM10_2_1>5)
		{
			TIM10_2_1 =0 ;
		}	
	}

值得一提的是,呼吸灯变换速度的实现,完全靠的是硬件,影子寄存器的实现,只能说666。

总结

关于整个工程目前遇到的一个影响整个工程质量的问题是如果发送数据给OLED屏幕过快的话,很可能会导致OLED屏幕乱码,需要对这个方面留点小心眼。
视频请移步到B站观看:https://www.bilibili.com/video/BV1wv4y1m7Xg/
关于整个工程代码:链接:https://pan.baidu.com/s/1wLzfx38t0ZWbsXt9Z_E-OQ?pwd=8888
提取码:8888

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
嵌入式系统是指集成了计算机处理器、存储器、输入输出接口、操作系统和应用软件等功能模块的微型电子系统,通常被用于特定的控制、监测、通信等领域。以下是我身边的两个嵌入式系统的分析: 1. 智能手表智能手表是一种集时钟、运动监测、通知提醒等功能于一体的智能穿戴设备。从嵌入式构成上,智能手表通常包括以下模块: - 处理器:智能手表通常使用低功耗的ARM架构处理器,用于控制各种硬件模块的运行。 - 存储器:智能手表使用闪存作为存储介质,用于存储操作系统、应用程序和用户数据等信息。 - 传感器:智能手表通常配备各种传感器,如加速度传感器、陀螺仪、心率传感器等,用于实现运动监测功能。 - 显示屏:智能手表使用OLED或LCD显示屏,用于显示时间、通知信息、运动数据等内容。 - 电池:智能手表使用锂离子电池,提供电源支持。 - 操作系统:智能手表使用轻量级的操作系统,如Android Wear或watchOS。 2. 智能家居控制器:智能家居控制器是一种用于控制智能家居设备的嵌入式系统。从嵌入式构成上,智能家居控制器通常包括以下模块: - 处理器:智能家居控制器通常使用ARM架构处理器,用于控制各种硬件模块的运行。 - 存储器:智能家居控制器使用闪存作为存储介质,用于存储操作系统、应用程序和用户数据等信息。 - 通信模块:智能家居控制器配备Wi-Fi、蓝牙或ZigBee等通信模块,用于与智能家居设备进行通信。 - 输入输出接口:智能家居控制器通常配备各种输入输出接口,如USB、HDMI、音频输出等,用于连接各种外部设备。 - 操作系统:智能家居控制器使用嵌入式Linux或RTOS等操作系统,提供应用程序和驱动程序的支持。 以上是我身边的两个嵌入式系统的分析,它们的嵌入式构成不同,但都具有高度集成化和低功耗等特点,能够满足不同的应用需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

所有的努力都是为了能更好的睡觉

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

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

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

打赏作者

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

抵扣说明:

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

余额充值