模拟面试:
一、GPIO是什么?
答:通用输入输出接口,可以作为单片机和外部设备连接的桥梁。
二、VCC是什么? VCC通常是多少V?
答:电源,通常是3.3V和5V。
三、FreeRTOS任务有几种状态,分别是什么状态?
答:4种,分别是: 就绪态、运行态、阻寒态、挂起态。
四、PWM是什么东西?
答:脉冲宽度调制,可以通过控制电压来改变外部设备的状态。
五、占空比是什么?
答:高电平占整个周期时间的比例,即(高电平 / 周期时间) * 100%。
六、FreeRTOS是什么?
答: 是一种开源的、实时的操作系统,是一款轻量型的操作系统。
七、FreeRTOS 和 Linux 的区别?
答:1.内存占用: FreeRTOS 是一款轻量级的操作系统占用内存较小,Linux 占用内存较大。
2.性能: FreeRTOS 没有 Linux 操作系统性能强,Linux 支持网络、OT等等,Linux功能较多。
3.应用领域: FreeRTOS 主要是运用在嵌入式设备上,Linux 既可以运行在嵌入式设备,也可以运行在桌面系统上。
4.FreeRToS 是实时操作系统(可以在规定时间完成对应的任务),Linux 是通用操作系统。
八、描述一下串口的数据帧格式
答:帧数据有起始位、数据位、停止位,可以有校验位。
起始位: 标志着开始发送数据
数据位: 要发送的数据
停止位: 标志着一次数据发送的结束
校验位: 确保数据传输的正确性(可有可无)
九、定时器的定时时间怎么计算?
答:定时时间 (s) =(预分频系数 + 1) * (重装值 + 1)/系统时钟主频 (MHZ)
十、ADC是什么?模拟信号? 数字信号?
答:ADC: 模拟数字信号转换器
模拟信号: 连续的信号
数字信号:不连续的信号 (0和1组成)
十一、FreeRTOS创建任务有几种方式? 描述一下
答:动态创建和静态创建两种。
(1)动态创建任务无需指定具体的栈,只需要给定栈的大小即可,它会调用 vportmalloc函数自己指定,静态创建任务既需要制定具体的栈,可以使用数组来指定,也需要给定栈的大小
(2)动态创建任务耗费的资源比静态创建任务耗费的资源多
(3)动态创建任务适用于需要随时申请和随时释放的场景,而静态创建任务适用于明确任务具体数目的场景
十二、串口中波特率是干什么的? 设置需要注意什么?
答:用来表示数据发送和接收的速度快慢的,单位是 bit;
电脑和单片机通信时要注意一定要将二者波特率设为一致。
十三、DMA是什么? 作用是什么?
答:DMA: 直接存储器存储(既可以存数据,也可以读数据)。
作用: 1.减轻CPU的负担,提高了CPU的资源利用率;
2.DMA传输数据较快,适用于处理图片、视频、音频等数据量较大的场合。
十四、任务的挂起和任务的删除有什么区别?
答:任务挂起时: 任务不运行但存在,再次使用时只需要从挂起状态中唤醒即可,无需重新创建
任务删除时: 任务不存在,再次使用时需要重新创建
十五、FreeRTOS有哪几种调度算法?
答:抢占式调度、时间片轮转、协作式调度
1.总结任务调度算法之间的区别,重新实现一遍任务调度算法的代码。
(1)抢占式调度:高优先级任务可以打断低优先级任务,用于任务优先级不同的任务
(2)时间片轮转:相同优先级的任务,分配相同的时间片(一般为 1ms),当任务的时间片用完后,必须退出
(3)协作式调度:一般使用 osDelay 实现,任务之间协商着执行,相当于是:抢占式调度+时间片轮转
2.总结静态创建任务和动态创建任务的区别,以及动态创建任务和静态创建任务的源码分析步骤。
(1)动态创建任务无需指定具体的栈,只需要给定栈的大小即可,它会调用 vportmalloc函数自己指定,静态创建任务既需要制定具体的栈,可以使用数组来指定,也需要给定栈的大小
(2)动态创建任务耗费的资源比静态创建任务耗费的资源多
(3)动态创建任务适用于需要随时申请和随时释放的场景,而静态创建任务适用于明确任务具体数目的场景
3.总结任务的状态,以及任务状态之间的转换关系。
任务的状态:就绪态、运行态、阻塞态、挂起态
就绪态--->运行态:任务一经创建就处于就绪态,当程序执行任务时,就进入运行态
运行态--->就绪态:当任务执行结束后,就会回到就绪态
就绪态--->挂起态:通过 vTaskSuspend() 函数可以将任务挂起,可以实现从就绪态转换为挂起态
挂起态--->就绪态:通过 vTaskResume() 函数可以将任务从挂起状态中恢复,可以实现从挂起态转换为就绪态
运行态--->挂起态:通过 vTaskSuspend() 函数可以将任务挂起,可以实现从运行态转换为挂起态
阻塞态--->挂起态:通过 vTaskSuspend() 函数可以将任务挂起,可以实现从阻塞态转换为挂起态
阻塞态--->就绪态:当等待的事件完成后(时间、信号量、互斥量等满足条件时),就可以从阻塞态进入就绪态
运行态--->阻塞态:当处于等待事件发生的状态时,就会进入阻塞态
4.抢占式调度
void StartDefaultTask(void *argument)
{/* USER CODE BEGIN StartDefaultTask *//* Infinite loop */for(;;){printf("StartDefaultTask is start\r\n");if(Task2Handle == NULL){Task2Handle = osThreadNew(Task2, NULL, &Task2_attributes);}printf("StartDefaultTask is end\r\n");osDelay(500);}/* USER CODE END StartDefaultTask */
}/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
void Task2(void *argument)
{for(;;){printf("Task2 is running\r\n");osDelay(500);}
}
5.时间片轮转
void StartDefaultTask(void *argument)
{/* USER CODE BEGIN StartDefaultTask *//* Infinite loop */int i=0;for(;;){printf("StartDefaultTask is start\r\n");for(i = 0;i < 10000000;i++){; //消耗时间}printf("StartDefaultTask is end\r\n");osDelay(500);}/* 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)
{/* USER CODE BEGIN StartTask02 *//* Infinite loop */for(;;){printf("StartTask02 is running\r\n");osDelay(500);}/* USER CODE END StartTask02 */
}