一、实验验证擦除操作
main.c
int main(void)
{
// 定义变量
uint8_t mK1[32]; //按照逻辑读方式从指定flash区域中读取的数据
uint8_t result; //判断扇区是否为空标识
// 关总中断
DISABLE_INTERRUPTS;
// Flash初始化
flash_init();
// 开总中断
ENABLE_INTERRUPTS;
// 擦除第52扇区
flash_erase(52);
result = flash_isempty(52,MCU_SECTORSIZE); // 判断第52扇区是否为空
printf("QAQ QAQ QAQ QAQ\n");
printf("第52扇区是否为空,1表示空,0表示不空: %d\n",result);
// 第一次写入
flash_write(52,0,32,(uint8_t *) "陶晓杰.");
flash_read_logic(mK1,52,0,32); //从52扇区读取32个字节到mK1中
printf("第一次: %s\n",mK1);
result = flash_isempty(71,MCU_SECTORSIZE); // 判断第52扇区是否为空
printf("第52扇区是否为空,1表示空,0表示不空: %d\n",result);
// 第二次写入
flash_write(52,0,32,(uint8_t *) "陶晓杰!");
flash_read_logic(mK1,52,0,32); //从52扇区读取32个字节到mK1中
printf("第二次: %s\n",mK1);
printf("qaq qaq qaq qaq\n");
// 请在第一次运行之后找到flash.c的函数flash_write,里面有一个擦除扇区操作,注释掉在编译运行一次
// 看看结果如何
}
- 第一次运行
2.注释掉擦除操作后
可见,如果不进行擦除操作,就无法写入新的数据。
二、ADC模块中,显示当前温度和芯片内部温度
#define GLOBLE_VAR
#include "includes.h" //包含总头文件
//----------------------------------------------------------------------
//声明使用到的内部函数
//main.c使用的内部函数声明处
void Delay_ms(uint16_t u16ms);
float Regression_Ext_Temp(uint16_t tmpAD); //环境温度AD值转为实际温度
float Regression_MCU_Temp(uint16_t mcu_temp_AD); //MCU温度AD值转为实际温度
//----------------------------------------------------------------------
//主函数,一般情况下可以认为程序从此开始运行(实际上有启动过程,参见书稿)
//主函数
int main(void)
{
uint16_t mcu_temp_AD; //芯片温度AD值
float mcu_temp; //芯片温度回归值
uint16_t temp_AD; //外接热敏电阻(温度)AD值
float temp; //外部热敏电阻(温度)回归值
adc_init(AD_MCU_TEMP,0); //初始化AD芯片温度模块
mcu_temp_AD = adc_read(AD_MCU_TEMP); //读取mcu温度通道AD值
temp_AD=adc_read(AD_TEMP);
mcu_temp_AD = adc_read(AD_MCU_TEMP);
mcu_temp=adc_mcu_temp(mcu_temp_AD); //将芯片温度AD值转换成实际温度
printf("mcu_temp_AD = %d\n",mcu_temp_AD);
printf("芯片内部温度为:%6.2lf℃\r\n",mcu_temp);
temp_AD = adc_ave(AD_TEMP,8); //获取外部热敏电阻(温度)AD值
temp=tempRegression(temp_AD); //将外部热敏电阻(温度)AD值转换成实际的温度
printf("temp_AD = %d\n",temp_AD);
if(temp==-274){
printf("热敏电阻温度AD值异常,请检查相关硬件\n");
}else{
printf("室温为:%6.2f℃\r\n",temp);
}
} //main函数(结尾)
初始温度
触碰芯片(冷触碰)后,温度上升较慢
触碰热敏电阻(热触碰)后,温度上升较快
一、注释
CANMode = CAN_MODE_NORMAL; // 设置CAN模式为正常模式
if(can_send_once(canNo,DestID,send_length,buff+len-i) == 1) // 尝试发送一次CAN消息
{
return 1; // 如果发送成功,则返回1
}
if ((CAN_ARR[canNo-1]->RF0R & CAN_RF0R_FMP0) == 0U) // 检查FIFO 0是否为空
{
return 1; // 如果FIFO 0为空,则返回1
}
len = (CAN_RDT0R_DLC & CAN_ARR[canNo-1]->sFIFOMailBox[RxFifo].RDTR) >> CAN_RDT0R_DLC_Pos; // 从接收FIFO的数据长度代码中提取数据长度
if (RxFifo == CAN_RX_FIFO0)
{
SET_BIT(CAN_ARR[canNo-1]->RF0R, CAN_RF0R_RFOM0); // 释放FIFO 0的消息溢出标志
}
if(Can_Rx_FifoNo == CAN_RX_FIFO0)
SET_BIT(CAN_ARR[canNo-1]->IER, CAN_IER_FMPIE0); // 启用FIFO 0的消息挂起中断
NVIC_EnableIRQ(table_irq_can[Can_Rx_FifoNo]); // 启用CAN中断(根据接收FIFO编号)
transmit_mailbox = (register_tsr & CAN_TSR_CODE) >> CAN_TSR_CODE_Pos; // 从发送状态寄存器中提取传输邮箱号
if(DestID <= 0x7FFU) // 如果目标ID小于或等于0x7FF,则发送帧为标准帧
{
CAN_ARR[canNo-1]->sTxMailBox[transmit_mailbox].TIR = ((DestID << CAN_TI0R_STID_Pos)|CAN_ID_STD|rtr); // 设置发送邮箱的标识符寄存器为标准帧
}
else
{
CAN_ARR[canNo-1]->sTxMailBox[transmit_mailbox].TIR = ((DestID << CAN_TI0R_EXID_Pos)|CAN_ID_EXT|rtr); // 设置发送邮箱的标识符寄存器为扩展帧
}
WRITE_REG(CAN_ARR[canNo-1]->sTxMailBox[transmit_mailbox].TDHR, ...); // 假设这里应该有数据写入到数据高寄存器,但数据被省略了
SET_BIT(CAN_ARR[canNo-1]->sTxMailBox[transmit_mailbox].TIR, CAN_TI0R_TXRQ); // 设置发送请求标志以启动发送
RCC->APB1ENR1 |= RCC_APB1ENR1_CAN1EN; // 使能CAN1时钟
GPIOA->MODER |= (GPIO_MODER_MODE11_1|GPIO_MODER_MODE12_1); // 配置GPIO引脚为通用推挽输出
GPIOA->AFR[1] |= (GPIO_AFRH_AFSEL11_0|GPIO_AFRH_AFSEL11_3)|(GPIO_AFRH_AFSEL12_0|GPIO_AFRH_AFSEL12_3); // 配置GPIO引脚的复用功能(用于CAN通信)
// 清除CAN模块的睡眠模式位
CLEAR_BIT(CAN_ARR[canNo-1]->MCR, CAN_MCR_SLEEP);
// 等待直到CAN模块退出睡眠模式(SLAK位清零)
while ((CAN_ARR[canNo-1]->MSR & CAN_MSR_SLAK) != 0U)
// 请求CAN模块进入初始化模式
SET_BIT(CAN_ARR[canNo-1]->MCR, CAN_MCR_INRQ);
// 清除TTCM(时间触发通信模式)位
CLEAR_BIT(CAN_ARR[canNo-1]->MCR, CAN_MCR_TTCM);
// 清除ABOM(自动离线管理)位
CLEAR_BIT(CAN_ARR[canNo-1]->MCR, CAN_MCR_ABOM);
// 清除AWUM(自动唤醒模式)位
CLEAR_BIT(CAN_ARR[canNo-1]->MCR, CAN_MCR_AWUM);
// 设置NART(无自动重传)位
SET_BIT(CAN_ARR[canNo-1]->MCR, CAN_MCR_NART);
// 清除RFLM(接收FIFO锁定模式)位
CLEAR_BIT(CAN_ARR[canNo-1]->MCR, CAN_MCR_RFLM);
// 清除TXFP(发送FIFO优先级)位
CLEAR_BIT(CAN_ARR[canNo-1]->MCR, CAN_MCR_TXFP);
// 配置CAN的比特率和操作模式(包括预分频器、同步跳转宽度等)
CAN_ARR[canNo-1]->BTR |= ((uint32_t)(Prescaler-1)|CAN_SJW_1TQ|CAN_BTR_TS1_1|CAN_BTR_TS1_0|CAN_BTR_TS2_2|CANMode);
// 清除初始化请求位,使CAN模块退出初始化模式
CLEAR_BIT(CAN_ARR[canNo-1]->MCR, CAN_MCR_INRQ);
// 等待直到CAN模块响应初始化请求(INAK位清零)
while ((CAN_ARR[canNo-1]->MSR & CAN_MSR_INAK) != 0U)
// 如果CanID小于或等于0x7FF,则将其左移以匹配CAN_TI0R_STID_Pos的位位置
if(CanID <= 0x7FFU) CanID = CanID << CAN_TI0R_STID_Pos;
// 提取CanID的高16位
FilterIdHigh = (CanID >> 16) & 0xFFFF;
// 提取CanID的低16位
FilterIdLow = (CanID & 0xFFFF);
// 设置过滤器掩码的高16位(通常用于匹配多个ID)
FilterMaskIdHigh = 0xFFE0;
// 设置过滤器掩码的低16位(通常为0以仅匹配ID的高位)
FilterMaskIdLow = 0x0000;
// 计算用于设置或清除过滤器激活寄存器的位掩码
filternbrbitpos = (uint32_t)1 << (FilterBank & 0x1FU);
// 设置过滤器初始化模式 (FINIT=1),允许进行过滤器配置
SET_BIT(CAN_ARR[canNo-1]->FMR, CAN_FMR_FINIT);
// 清除过滤器激活位,确保在配置前过滤器未被激活
CLEAR_BIT(CAN_ARR[canNo-1]->FA1R, filternbrbitpos);
// 如果过滤器配置为32位模式
if (FilterScale == CAN_FILTERSCALE_32BIT)
{
// 设置相应的过滤器规模为32位
SET_BIT(CAN_ARR[canNo-1]->FS1R, filternbrbitpos);
// 配置过滤器寄存器FR1
CAN_ARR[canNo-1]->sFilterRegister[FilterBank].FR1 =
// 如果过滤器模式为IDMASK(即使用掩码匹配)
if (FilterMode == CAN_FILTERMODE_IDMASK)
{
// 清除过滤器模式位,使用掩码模式
CLEAR_BIT(CAN_ARR[canNo-1]->FM1
}
//退出过滤器初始化模式 (FINIT=0)
CLEAR_BIT(CAN_ARR[canNo-1]->FMR, CAN_FMR_FINIT); //2024.6
二、实验结果
结果截图:
连线图片:
实验原理图:
CAN原理: