admin管理员组文章数量:1647017
本人初学freertos,手里只有一块STM32MP157裸板,屏幕都没有,显示都是通过串口模拟的,自己想了一个实验项目,可以用来熟悉freertos的基本内容。谢谢
目录
概述:
主要程序:
实验效果
源码
概述:
//使用百问网STM32MP157(仅使用M4内核)开发板移植FreeRTOS
//利用板载AP3216C传感器收集光和距离数据
//模拟实现手机的密码解锁功能
//模拟实现手机的实时PWM调光功能
//模拟实现手机或平板的合盖息屏(保护套息屏)功能
//模拟实现手机自动休眠锁屏功能
//硬件外设使用:key1:改变密码数字
// key2:确定密码并切换密码位置
// led(yellow):模拟手机屏幕
// led(green):提示手机是否解锁成功
// AP3216C:收集光和距离数据
//涉及相关外设功能:FreeRTOS(队列,任务状态,软件定时器)、I2C、串口、标准IO、定时器PWM
效果:双键一起按唤醒屏幕后,可进行输入密码解锁屏幕,同时黄色LED(模拟手机屏幕)随环境光亮暗变化,若有物体贴紧传感器,则会锁屏并熄灭屏幕,若唤醒屏幕后20秒未按按键,则自动休眠锁屏。
主要程序:
app_freertos.c
defaulttask:运行解锁屏幕程序
task02:模拟手机PWM自适应调光
task03 :模拟合盖息屏程序
/*app_freertos.c*/
void StartDefaultTask(void *argument) //任务一defaultTask中运行解锁屏幕程序
{
/* USER CODE BEGIN StartDefaultTask */
/* Infinite loop */
for(;;)
{
vTaskSuspend(defaultTaskHandle); //在屏幕未唤醒时挂起任务一,等待双键点亮屏幕
osTimerStart(myTimer01Handle,20000); //开启软件定时器(自动重装载),定时为20s,用于模拟手机自动锁屏
mycodefunc(); //调用密码输入屏幕解锁程序
osDelay(1);
}
/* USER CODE END StartDefaultTask */
}
/* USER CODE BEGIN Header_StartTask02 */
/**
* @brief Function implementing the myTask02 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTask02 */
void StartTask02(void *argument) //task02任务为模拟手机PWM自适应调光,用黄色LED模拟手机屏幕
{
/* USER CODE BEGIN StartTask02 */
/* Infinite loop */
for(;;)
{
vTaskSuspend(myTask02Handle); //在屏幕未唤醒时挂起任务二,等待双键点亮屏幕
mypwmfunc(); //调用PWM实时自适应调光程序
osDelay(1);
}
/* USER CODE END StartTask02 */
}
/* USER CODE BEGIN Header_StartTask03 */
/**
* @brief Function implementing the myTask03 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTask03 */
void StartTask03(void *argument) //task03任务为双键唤醒屏幕程序和实时模拟合盖熄灭屏幕程序(利用距离传感器)
{
/* USER CODE BEGIN StartTask03 */
/* Infinite loop */
for(;;)
{
if(key_1==down&&key_2==down){ //当开发板双按键同时按下,软件消抖
vTaskDelay(5);
if(key_1==down&&key_2==down){
vTaskResume(defaultTaskHandle); //此时恢复defaulttask和task02,屏幕正常使用,进行正常解锁和输入密码等
vTaskResume(myTask02Handle);
//ledon();
vTaskDelay(1000);
}
}
mypsfunc(); //调用模拟合盖息屏程序
osDelay(1);
}
/* USER CODE END StartTask03 */
}
/* Callback01 function */
void Callback01(void *argument) //软件定时器回调程序(利用freertos自带软件定时器功能)
{ //当超过20s未使用按键重置软件定时器时间,则会调用回调函数
/* USER CODE BEGIN Callback01 */
ledoff(); //绿色LED熄灭,表示已上锁,解锁需要重新输入密码
vTaskSuspend(myTask02Handle); //挂起task02,实时PWM调光功能关闭
pwmoff(); //黄色LED熄灭,表示屏幕熄灭
printf("************屏幕上边界************\r\n"); //串口打印此时屏幕状态,什么都没有
printf(" \n");
printf(" \n");
printf(" \n");
printf(" \n");
printf(" \r\n");
printf("************屏幕下边界************\r\n");
printf("已锁屏 \r\n");
vTaskSuspend(defaultTaskHandle); //挂起defaulttask任务,暂停按键输入任务
/* USER CODE END Callback01 */
}
my_key.c
defaulttask中调用的解锁屏幕程序
uint8_t code[5]={'X','X','X','X'}; //设定四位密码,默认显示为XXXX
uint8_t temp[11]={'0','1','2','3','4','5','6','7','8','9'}; //数字密码0-9
uint8_t rightcode[]="1234"; //在这里设定密码,默认为1234
extern osThreadId_t defaultTaskHandle; //外部声明相关句柄
extern osTimerId_t myTimer01Handle;
void mycodefunc(){
printf("************屏幕上边界*********\r\n"); //屏幕亮起,提示输密码
printf("请输入密码,按KEY2确定.\n");
printf(" \n");
printf(" \n");
printf(" \n");
printf(" \n");
printf(" \r\n");
printf("************屏幕下边界*********\r\n");
vTaskDelay(500);
uint8_t i=0,j=0;
while(i<4){
if(key_1==down){ //按key1更改数字
vTaskDelay(5);
if(key_1==down){
xTimerReset(myTimer01Handle,100);
if(j==11){
code[i]=temp[0];
j=0;
myprint();
}
else{
code[i]=temp[j++];
myprint();
}
vTaskDelay(500);
}
}
if(key_2==down){ //按key2确认并切换到下一位
vTaskDelay(5);
if(key_2==down){
xTimerReset(myTimer01Handle,100);
i++;
j=0;
//myprint();
vTaskDelay(500);
}
}
}
if(i==4&&strcmp(code,rightcode)!=0) printf("密码错误!请重新输入.\r\n"),mycodefunc(); //检测密码是否正确
if(i==4){ //密码正确,提示已解锁,绿色LED亮代表已经解锁
ledon();
printf("*******************************\r\n");
printf("屏幕已解锁. \r\n");
}
}
void myprint(){
for(uint8_t i=0;code[i]!='\0';i++)
printf("%c",code[i]);
printf("\r\n");
}
my_pwm.c
实时PWM调光和合盖息屏模拟程序
void mypwmfunc(){ //PWM调光函数,黄色LED会随外部光照情况调整自身亮暗
uint16_t als,ps;
while(1){
AP3216_Read_ALS_Data(&als); //读光照和距离数据
AP3216_Read_PS_Data(&ps);
if(myQueue01Handle!=0){ //将ps数据通过队列传给task03
if(xQueueSend(myQueue01Handle,&ps,1)!=pdTRUE){
xQueueReset(myQueue01Handle);
}
}
sprintf(dec,"%x",als);
uint16_t ret=hexToDec(dec); //将十六进制als数据转换为十进制
pwmon();
__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,ret); //通过改变PWM的CCR值改变占空比调节亮度
if(key_1==down||key_2==down){ //若在运行过程中有按键被按下,重置软件定时器,代表此时正在使用屏幕,不锁屏
xTimerReset(myTimer01Handle,100);
}
}
}
void mypsfunc(){ //模拟合盖息屏程序
uint16_t ps=0;
if(myQueue01Handle!=0){ //从队列读取task02发出的ps数据
if(xQueueReceive(myQueue01Handle,&ps,1)==pdTRUE){
if(ps>0x1000){ //当距离过近时熄灭屏幕
vTaskDelay(50);
if(ps>0x1000){
ledoff(); //绿色LED熄灭,表示锁屏
vTaskSuspend(myTask02Handle); //调光程序挂起
pwmoff(); //屏幕熄灭
printf("************屏幕上边界*********\r\n");
printf(" \n");
printf(" \n");
printf(" \n");
printf(" \n");
printf(" \r\n");
printf("************屏幕下边界*********\r\n");
printf("已锁屏. \r\n");
vTaskSuspend(defaultTaskHandle);
xQueueReset(myQueue01Handle);
}
}
}
}
}
my_AP3216C.c
芯片驱动部分
oid AP3216_Read_PS_Data(uint16_t *pPS) //读距离传感器数据
{
taskENTER_CRITICAL(); //特别注意此时任务应进入临界段,否则读i2c会容易卡死
uint8_t ps_l = 0, ps_h = 0;
ps_l = AP3216_ReadOneByte(PS_L_ADDR);
ps_h = AP3216_ReadOneByte(PS_H_ADDR);
if( (ps_l&0x40)==0x40)
{
*pPS = 0;
}
else
{
*pPS = ((ps_h&0x1F)<<8) | (ps_l&0x0F);
}
taskEXIT_CRITICAL();
}
void AP3216_Read_ALS_Data(uint16_t *pALS) //读光传感器数据
{
taskENTER_CRITICAL(); //特别注意此时任务应进入临界段,否则读i2c会卡死
uint8_t als_l = 0, als_h = 0;
als_l = AP3216_ReadOneByte(ALS_L_ADDR);
als_h = AP3216_ReadOneByte(ALS_H_ADDR);
*pALS = (als_h<<8) | (als_l);
taskEXIT_CRITICAL();
}
实验效果
【基于FreeRTOS模拟手机屏幕自动调光,屏幕保护,屏幕解锁功能实验演示视频】 https://www.bilibili/video/BV1LW4y147fE/?share_source=copy_web&vd_source=02efc9b8955e0c6589b36882af845feb
源码
https://github/fredning/freertos-phone-sim
版权声明:本文标题:STM32+FreeRTOS模拟手机PWM调光、屏幕解锁、定时休眠小项目 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/xitong/1729471894a1202015.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论