11、什么叫上升沿和下降沿触发
- 上升沿触发:信号从低电平跳变为高电平时触发事件(如中断、采样)。
- 下降沿触发:信号从高电平跳变为低电平时触发事件。
12、数码管扫描频率?共阴极和共阳极的区别?
通常来说扫描频率需≥50Hz,这是由于人眼的视觉暂留,如果低于这个频率,你会明显感觉到屏幕在闪烁,长时间观看容易疲劳。推荐 100Hz 左右。
- 共阴极与共阳极区别
- 共阴极:所有段选引脚接 LED 阳极,公共端接 GND,段选高电平点亮。
- 共阳极:所有段选引脚接 LED 阴极,公共端接 VCC,段选低电平点亮。
13.ADC采样位数代表什么?什么因素影响ADC精度和转换速率?有什么滤波算法?
- 采样位数
表示 ADC 能将模拟量转换为数字量的精度,如 12 位 ADC 的分辨率为1/(2^12) = 1/4096,即最小可区分Vref/4096的电压变化(Vref 为参考电压)。
- 影响 ADC 精度和速率的因素
- 精度:参考电压稳定性、输入噪声、非线性误差、温度漂移
- 速率:ADC 时钟频率、转换位数(位数越高,速率通常越低)、采样时间
- 滤波算法
- 软件滤波:滑动平均、中位值滤波、限幅滤波(适合低速采样)
- 硬件滤波:RC 低通滤波(滤除高频噪声)
14.中断如何设置?中断中任务过多有什么危害?
- 中断设置步骤(以 STM32 为例):
- 使能中断控制器(NVIC)对应通道;
- 配置触发源;
- 编写中断服务程序(ISR),处理核心逻辑。
- 中断中任务过多的危害
- 中断响应延迟:阻塞其他高优先级中断,导致实时性下降
- 栈溢出风险:ISR 中执行复杂操作(如大量局部变量、函数调用)可能耗尽栈空间
- 数据一致性问题:长时间占用中断可能导致主程序与 ISR 共享数据更新不及时
原则:ISR 应 快进快出,仅处理紧急操作,复杂逻辑放到主程序。
15.波特率是什么?
比特率:每秒钟传送的比特数量,又称为传信率。比特率基本单位为bit/s或bps。
波特率:每秒钟传送的符号(码元)数量,又称为传码率,单位是波特(Baud、B,即symbol/s)
16.串口通信起始位如何判定?i2c总线仲裁?
- 串口起始位判定:UART 通信中,空闲状态为高电平,当检测到一个持续 1 位时间的低电平时,判定为起始位,随后开始接收数据位。
- I2C 总线仲裁:当多主设备同时发送数据时,通过 “线与” 逻辑仲裁
- 若某设备发送高电平,而检测到总线为低电平,则该设备退出仲裁(失去总线控制权);
- 最终只有一个设备能继续占用总线,保证数据传输不冲突。
17、IIC 速率
IIC协议定义了多种数据传输速率标准,以适应不同的应用需求。以下是IIC协议的主要数据传输速率标准:
- 标准模式(S) :速率为100 kbps。
- 快速模式(F) :速率为400 kbps。
- 高速模式(HS) :速率为3.4 Mbps。
- 超高速模式 :速率为5 Mbps。
18、中断函数可不可以有参数、返回值,在中断中可以进行 printf 函数打印吗?
中断服务函数注意的四大点:
- 中断服务函数不能传入参数;
- 中断服务函数不能有返回值;
- 中断服务函数应该做的短小精悍
- 不推荐在中断服务函数中使用printf函数,printf函数可能会引入较大的代码体积和运行时开销,而在中断服务中不应该执行过多复杂操作,以免影响实时性和系统性能。
19、I2C、SPI、UART 发送高低位
- I2C先发送数据最高位,就像我们写数一样(这里面只有这个协议读法含有数字)
- SPI可配置
- UART 先发送数据最低位
20、手敲IIC
(我遇到过两回面试手敲IIC。)
这个一般面试官会给你说明一下,然后你可以按照说明进行编写。其实不需要太严谨,只要大致思路、流程正确即可。
重点分为起始、传送(读\写)、停止、等待应答。
(下面是直接找的,可以参考下,网上有很多,大致思路、流程正确即可)
/*-------------------------------------------------*/
/*函数名:IIC起始信号 */
/*参 数:无 */
/*返回值:无 */
/*-------------------------------------------------*/
void IIC_Start(void)
{
SDA_OUT(); //SDA线输出模式
IIC_SDA_H; //SDA拉高
IIC_SCL_H; //SCL拉高
Delay_Us(4); //延时
IIC_SDA_L; //SCL高电平的时候,SDA由高到低,起始信号
}
/*-------------------------------------------------*/
/*函数名:IIC停止信号 */
/*参 数:无 */
/*返回值:无 */
/*-------------------------------------------------*/
void IIC_Stop(void)
{
SDA_OUT(); //SDA线输出模式
IIC_SDA_L; //SDA拉低
IIC_SCL_H; //SCL拉高
Delay_Us(4); //延时
IIC_SDA_H; //SCL高电平的时候,SDA由低到高,发出停止信号
}
/*-------------------------------------------------*/
/*函数名:等待应答 */
/*参 数:无 */
/*返回值:0:成功 1:失败 */
/*-------------------------------------------------*/
char IIC_Wait_Ack(void)
{
unsigned char timeout=0; //定义一个变量,用于计算超时时间
IIC_SDA_H; //SDA拉高
SDA_IN(); //SDA线输入模式
IIC_SCL_H; //SCL拉高
while(READ_SDA){ //等待SDA变低电平,表示应答到来,不然一直while循环,直到超时
timeout++; //超时计数+1
if(timeout>250){ //如果大于250
IIC_Stop(); //发送停止信号
return 1; //返回1,表示失败
}
Delay_Us(2); //延时
}
IIC_SCL_L; //SCL拉低
Delay_Us(20); //延时
return 0; //返回0,表示成功
}
/*-------------------------------------------------*/
/*函数名:读取一个字节 */
/*参 数:ack:是否发送应答 1:发 0:不发 */
/*返回值:读取的数据 */
/*-------------------------------------------------*/
unsigned char IIC_Read_Byte(unsigned char ack)
{
unsigned char i; //定义一个变量用于for循环
unsigned char receive; //定义一个变量用于保存接收到的数据
receive = 0; //清除receive,准备接收数据
SDA_IN(); //SDA设置为输入
IIC_SCL_L; //SCL拉低
Delay_Us(20); //延时
for(i=0;i<8;i++){ //for循环,一位一位的读取
IIC_SCL_H; //SCL拉高
Delay_Us(20); //延时
receive<<=1; //左移一位,准备下次的读取
if(READ_SDA)receive++; //读取数据
Delay_Us(20); //延时
IIC_SCL_L; //SCL拉低
Delay_Us(20); //延时
}
if(!ack){ //不需要发送
SDA_OUT(); //SDA线输出模式
IIC_SDA_H; //时钟脉冲的高电平期间保持稳定的高电平
IIC_SCL_H; //SCL拉高
Delay_Us(2); //延时
IIC_SCL_L; //SCL拉低
}else{ //需要发送
SDA_OUT(); //SDA线输出模式
IIC_SDA_L; //时钟脉冲的高电平期间保持稳定的低电平
IIC_SCL_H; //SCL拉高
Delay_Us(2); //延时
IIC_SCL_L; //SCL拉低
IIC_SDA_H; //SDA拉高
}
return receive;
}
全部评论
(1) 回帖