写往年嵌入式真题自己所遇到一些小细节的错误
---------------------------------------------------UART----------------------------------------------------------------------
当接收到中断时:stm32g4xx_it.c文件中的函数void HardFault_Handler(void)将会调用void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)中断回调函数
在stm32g4xx_hal.c文件下,会有CubeMX自动生成的抢占优先级
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
NVIC_PRIORITYGROUP_4抢占优先级为组4表示可以选0~15范围
- //串口接收-中断回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
Disp_led(0xff);
HAL_Delay(300);
Disp_led(0x00);
HAL_UART_Receive_IT(&huart1,&rx_buffer,1);
}
在串口接收中断函数中调用了延迟函数HAL_Delay,执行该延迟函数需要进入滴答计时器,只有滴答计时器的中断正常实现;才能实现串口接收函数完整功能,并且才能跳出串口回调函数。
【解决方法】滴答定时器的中断优先级高于串口接收函数
Step1:在stm32g4xx_hal_conf.h文件下修改TICK_INT_PRIORITY优先级
Step2:并且在bsp_uart.c中修改串口中断优先级
---------------------------------------------------UART-第12届第一场------------------------------------------------
- 为什么检验字符串格式这段代码中,只能输入在串口中输入一次,才返回1;无论后面输入正确的字符串,都是0?修改Uart_count好像没效果
- 如果接收的字符串格式不符合要求,为何下面的写法是错误的
---------------------------------------------------KEY------------------------------------------------------------------------
解决方法:
- KeyPoint添加括号
- 在宏定义处添加括号
运算优先级:【>>、<<】 > 【^、^~】 >【 | 】
---------------------------------------------------LCD------------------------------------------------------------------------
---------------------------------------------------TIM配置-------------------------------------------------------------
定时器配置成计数模式:【目标:时间】
目的:配置时间间隔为1s
时钟源频率:80MHz
Psc=80000000/(7999+1)= 10000
Arr:(9999+1)/10000 = 1s
定时器配置成PWM脉冲模式:【目标:频率】
目的:配置时频率为100Hz
时钟源频率:80MHz
Psc=80000000/(7999+1)= 10000
Arr:10000/(99+1)= 100hz
设置PWM的占空比为50%:pulse = 50/100=50%
其Pulse指PWM中高电平所占的时钟周期
--------------------------------------频率测量和脉冲输出-------------------------------------------------------------
【要求】使用PA1完成频率测量功能
使用PA7完成脉冲输出功能
【计算】计算输入捕获频率:
主频80MHz
进行80分频,得到1MHz
输入捕获频率=1MHz/捕获值
PWM_Count = HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_2)+1;
其中,unsigned short int PWM_Count;
【转换】频率测量功能 -> 输入捕获-在配置中直接将分频设置为79即可
初始配置:Slave Mode:Reset Moed;Trigger Source:TI2FP2;
Input Capture direct mode
脉冲输出功能 -> 频率和占空比可调节
初始配置:Clock Source:Internal;Output Campare CH2
主频为80MHz;分频为79;计数周期为999;时钟周期:500
->频率为:1000Hz
->占空比:50%
--------------------------------------------------第十四届------------------------------------------------------------------
【要求】使用PA1引脚输出频率、占空比可调节的脉冲信号
使用PA7引脚完成脉冲捕获功能,测量输入到该引脚的信号频率
【转换】脉冲输出功能 -> 频率占空比可调节
脉冲捕获 -> 测量输入引脚到该信号的频率
【PWM输出--PA1详细要求】PWM输出信号通过电位器R37进行调节,
关系式为:
0.25s频率变化增加或减少160
高低模式切换时,保证PWM的值不变
【频率测量具体要求】
/*-------------------长按键问题------------*/
Key_down和Key_up不能嵌套调用—循环进不去
【思路】在Key_down下先使Time_count清零,Key_up下判断计时的时长
长按键 |
if(View_Switch == 0x20) { if(Key_down & 0x08) { Time_Count = 0; } if(Key_up & 0x08) { if(Time_Count < 2000) { ucLed = 0x10; } else { ucLed = 0x01; } } } |
TIM6基础定时器所用的计时变量Time_count应当注意定义变量类型,此处用unsigned int
---------------------------------------------------可编程电阻-------------------------------------------------------------
可编程电阻
---------------------------------------------------I2C-------------------------------------------------------------------------
I2C即两线式串行总线,由数据线SDA和时钟SCL构成的串行总线,可以发送和接收数据
- 数据线SDA和时钟线SCL必须通过上拉电路连接至正电源
- 传输:在CPU和被控IC之间,IC与IC之间进行双向传送
- 通信方式:半双工通信
开漏输出有两种情况:0或悬浮状态【若为浮空状态输出,那么上拉电路需连接至正电源】
- 应答信号
St1:发送器没发送一个字节【8bit】,就在时钟线SCL的第九个周期释放数据线,由接收器反馈一个应答信号。
St2:【成功接收字节】应答信号为低电平,即有效应答。
St3:【未成功接收字节】应答信号为高电平。
主设备等待从设备是否已成功应答
- 数据信息
St1:【空闲状态】I2C总线的SDA和SCL两条信号线同时处于高电平时。
St2:【控制信号】SDA线上的数据必须在时钟脉冲的高电压期间保持稳定。
St3:【数据传输】一个数据位在每一个时钟脉冲期间传输。
St4:【I2C发送一个字节】
/** * @brief I2C发送一个字节 * @param cSendByte 需要发送的字节 * @retval None */ |
void I2CSendByte(unsigned char cSendByte) { unsigned char i = 8; while (i--) { SCL_Output(0); delay1(DELAY_TIME); SDA_Output(cSendByte & 0x80); delay1(DELAY_TIME); cSendByte += cSendByte; delay1(DELAY_TIME); SCL_Output(1); delay1(DELAY_TIME); } SCL_Output(0); delay1(DELAY_TIME); } |
/** * @brief I2C接收一个字节 * @param None * @retval 接收到的字节 */ |
unsigned char I2CReceiveByte(void) { unsigned char i = 8; unsigned char cR_Byte = 0; SDA_Input_Mode(); while (i--) { cR_Byte += cR_Byte; SCL_Output(0); delay1(DELAY_TIME); delay1(DELAY_TIME); SCL_Output(1); delay1(DELAY_TIME); cR_Byte |= SDA_Input(); } SCL_Output(0); delay1(DELAY_TIME); SDA_Output_Mode(); return cR_Byte; } |
二线制串行EEPROM-24C02存储器
St1:02表示低工作电压的2K为串行电可擦除只读存储器,内部组织为256个字节,每个字节为8位,即256*8~2k
St2:
【双线串行接口】- 时钟线SCL,串行数据线SDA
【双线数据传送协议】- ISO/IEC7816-3同步协议:
8字节页面(1KB、2KB)16字节页面(4KB、8KB、16KB)写入
St3:【24C02芯片地址】1010_E3 E2 E1 (R=1,W=0)
- 读:0xA1
- 写:0xA0
St4:【写操作程序】
/** * 写操作程序 * 写入方式:8字节写页面时序 * pucBuf:写入的内容 *ucAddr:写地址 *ucNum:写入的字节大小 */ |
void i2c_Write(unsigned char* pucBuf,unsigned char ucAddr,unsigned char ucNum) { I2CStart(); I2CSendByte(0xa0); I2CWaitAck(); I2CSendByte(ucAddr); I2CWaitAck(); while(ucNum--) { I2CSendByte(*pucBuf++); I2CWaitAck(); } I2CStop(); delay1(500); } |
St5:【读操作程序】
/** *读操作程序 *读入方式:随机地址读取时序 */ |
void i2c_read(unsigned char* pucBuf,unsigned char ucAddr,unsigned char ucNum) { I2CStart(); I2CSendByte(0xa0); I2CWaitAck(); I2CSendByte(ucAddr); I2CWaitAck();
I2CStart(); I2CSendByte(0xa1); I2CWaitAck(); while(ucNum--) { *pucBuf ++ = I2CReceiveByte(); if(ucNum) I2CSendAck(); else I2CSendNotAck (); } I2CStop(); } |
【实际现象不符合预期】
【原因1】直接使用i2c_Write(EEPROM_String_1,0,5);和i2c_read(EEPROM_String_2,0,5),并顺序相连时会出现实际现象不符合预期。
【解决方法】需要在中间加入延迟函数HAL_Delay(1);
i2c_Write(EEPROM_String_1,0,5);//表示从EEPROM内部第0个地址开始写
HAL_Delay(1);
i2c_read(EEPROM_String_2,0,5)
【原因2】函数之间的位置
SDA_Output_Mode();
SCL_Output(0);
delay1(DELAY_TIME);
【解决方法】调换一下位置
SCL_Output(0);
delay1(DELAY_TIME);
SDA_Output_Mode();
注意顺序!!!
【原因3】I2Cinit()函数的位置
【解决方法】I2CInit();函数需要在Led_Key_Init();的后面
标签:SCL,字节,DELAY,delay1,unsigned,嵌入式,蓝桥,版本,Output From: https://blog.csdn.net/a_1940562/article/details/144716761