1、用实验验证,对于有数据的某扇区,如果没有擦除(Flash_erase),可否写入新数据?注:扇区号为学号 后2位,数据文本中要有姓名。
修改main,在逻辑擦除部分进行修改,先擦除写入和读取,再不拆除写入和读取,观察结果
//======================================================================
//文件名称:main.c(应用工程主函数)
//框架提供:SD-Arm(sumcu.suda.edu.cn)
//版本更新:20191108-20200419
//功能描述:见本工程的..\01_Doc\Readme.txt
//移植规则:【固定】
//======================================================================
#define GLOBLE_VAR
#include "includes.h" //包含总头文件
//----------------------------------------------------------------------
//声明使用到的内部函数
//main.c使用的内部函数声明处
//----------------------------------------------------------------------
//主函数,一般情况下可以认为程序从此开始运行(实际上有启动过程,参见书稿)
int main(void)
{
//(1)======启动部分(开头)==========================================
//(1.1)声明main函数使用的局部变量
uint32_t mMainLoopCount; //主循环次数变量
uint8_t mFlag; //灯的状态标志
uint32_t mLightCount; //灯的状态切换次数
uint8_t mK1[32]; //按照逻辑读方式从指定flash区域中读取的数据
uint8_t mK2[32]; //按照物理读方式从指定flash区域中读取的数据
uint8_t flash_test[32]={'A','B','C','D','E','F','G',' ','t',
'o',' ','S','o','o','c','h','o','w',' ',
'U','n','i','v','e','r','s','i','t','y','!'};
uint8_t result; //判断扇区是否为空标识
//(1.2)【不变】关总中断
DISABLE_INTERRUPTS;
//(1.3)给主函数使用的局部变量赋初值
mMainLoopCount=0; //主循环次数变量
mFlag='A'; //灯的状态标志
mLightCount=0; //灯的闪烁次数
//(1.4)给全局变量赋初值
//(1.5)用户外设模块初始化
gpio_init(LIGHT_BLUE,GPIO_OUTPUT,LIGHT_ON); //初始化蓝灯
//(1.6)使能模块中断
//(1.7)【不变】开总中断
ENABLE_INTERRUPTS;
printf("------------------------------------------------------\n");
printf("金葫芦提示: \n");
printf("(1)目的:flash扇区读写数据测试 \n");
printf("(2)测试过程:两种读写数据方式 \n");
printf(" 第一种:使用flash_write向50扇区写入一串字符串 \n");
printf(" 再用flash_read_logic将字符串读出,并用printf打印 \n");
printf(" 第二种:使用flash_write_physical向32扇区写入一串字符串\n");
printf(" 再用flash_read_physical将字符串读出,并用printf打印 \n");
printf("------------------------------------------------------\n");
//(1)======启动部分(结尾)==========================================
//擦除第61扇区
flash_erase(61);
//向50扇区第0偏移地址开始写32个字节数据
flash_write(61,0,32,(uint8_t *) "Welcome to Gzhu,CQL!");
flash_read_logic(mK1,61,0,32); //从61扇区读取32个字节到mK1中
printf("擦除后,逻辑读方式读取61扇区的32字节的内容: %s\n",mK1);
flash_write(61,0,32,(uint8_t *) "Erase the text!");
flash_read_logic(mK1,61,0,32); //从61扇区读取32个字节到mK1中
printf("不擦除,逻辑读方式读取61扇区的32字节的内容: %s\n",mK1);
//(2)======主循环部分(开头)========================================
for(;;) //for(;;)(开头)
{
//(2.1)主循环次数变量+1
mMainLoopCount++;
//(2.2)未达到主循环次数设定值,继续循环
if (mMainLoopCount<=12888999) continue;
//(2.3)达到主循环次数设定值,执行下列语句,进行灯的亮暗处理
//(2.3.1)清除循环次数变量
mMainLoopCount=0;
//(2.3.2)如灯状态标志mFlag为'L',灯的闪烁次数+1并显示,改变灯状态及标志
if (mFlag=='L') //判断灯的状态标志
{
mLightCount++;
printf("灯的闪烁次数 mLightCount = %d\n",mLightCount);
mFlag='A'; //灯的状态标志
gpio_set(LIGHT_BLUE,LIGHT_ON); //灯“亮”
printf(" LIGHT_BLUE:ON--\n"); //串口输出灯的状态
}
//(2.3.3)如灯状态标志mFlag为'A',改变灯状态及标志
else
{
mFlag='L'; //灯的状态标志
gpio_set(LIGHT_BLUE,LIGHT_OFF); //灯“暗”
printf(" LIGHT_BLUE:OFF--\n"); //串口输出灯的状态
}
} //for(;;)结尾
//(2)======主循环部分(结尾)========================================
} //main函数(结尾)
//======以下为主函数调用的子函数===========================================
//========================================================================
/*
知识要素:
(1)main.c是一个模板,该文件所有代码均不涉及具体的硬件和环境,通过调用构件
实现对硬件的干预。
(2)本文件中对宏GLOBLE_VAR进行了定义,所以在包含"includes.h"头文件时,会定
义全局变量,在其他文件中包含"includes.h"头文件时,
编译时会自动增加extern
*/
修改flash.c,注释掉flash_write函数内置了扇区擦除功能,否则写入时会自行擦除,然后再对flash_best函数的返回值判断,失败返回1。
//包含头文件
#include "flash.h"
#include "string.h"
#if(USE_BIOS_FLASH==0)//1代表函数继承自BIOS,0代表使用自带函数
//=================内部调用函数声明=====================================
//======================================================================
//函数名称:flash_write_DoubleWord
//函数返回:0-成功 1-失败
//参数说明:addr:目标地址,要求为4的倍数且大于Flash首地址
// (例如:0x08000004,Flash首地址为0x08000000)
// data:写入的双字
//功能概要:Flash双字写入操作
//======================================================================
uint8_t flash_write_DoubleWord(uint32_t addr,uint32_t data_l,uint32_t data_h);
//======================================================================
//函数名称:flash_Best
//函数返回:0-成功 1-失败
//参数说明:sect:待写入扇区号
// offset:待写入数据位置的偏移地址
// N:待写入数据字节数
// buf:待写入数据的首地址
//功能概要:首位地址都对齐的情况下的数据写入
//======================================================================
uint8_t flash_Best(uint16_t sect,uint16_t offset,uint16_t N,uint8_t *buf);
//======================================================================
//======================================================================
//=================外部接口函数=========================================
//======================================================================
//函数名称:flash_init
//函数返回:无
//参数说明:无
//功能概要:初始化flash模块
//编程来源:暂无
//======================================================================
void flash_init(void)
{
//(1)清除之前的编程导致的所有错误标志位
FLASH->SR &= 0xFFFFFFUL;
//(2)解锁Flash控制寄存器(CR)
if((FLASH->CR & FLASH_CR_LOCK) != 0U)
{
FLASH->KEYR = (uint32_t)FLASH_KEY1;
FLASH->KEYR = (uint32_t)FLASH_KEY2;
}
//(3)等待解锁操作成功
while((FLASH->CR & FLASH_CR_LOCK) != 0U);
//(4)等待之前最后一个flash操作完成
while( (FLASH->SR & FLASH_SR_BSY) != 0U);
//(5)清数据缓冲区
FLASH->ACR &= ~FLASH_ACR_DCEN_Msk;
//(6)清闪存即时编程位
FLASH->CR &= ~FLASH_CR_PG_Msk;
}
//======================================================================
//函数名称:flash_erase
//函数返回:函数执行执行状态:0=正常;1=异常。
//参数说明:sect:目标扇区号(范围取决于实际芯片,例如 STM32L433:0~127,每扇区2KB;
//功能概要:擦除flash存储器的sect扇区
//编程参考:STM32L4Rxxx芯片手册3.3.6主存储器擦除顺序
//======================================================================
uint8_t flash_erase(uint16_t sect)
{
//(1)等待之前最后一个flash操作完成
while( (FLASH->SR & FLASH_SR_BSY) != 0U);
//(2)清除之前的编程导致的所有错误标志位
FLASH->SR &= 0xFFFFFFUL;
//(3)清闪存即时编程位,将 PER 位置 1,并选择要擦除的页 (PNB)和相关存储区 (BKER)
FLASH->CR &= ~FLASH_CR_PG;
FLASH->CR |= FLASH_CR_PER;
FLASH->CR &= ~FLASH_CR_PNB;
FLASH->CR |= (uint32_t)(sect << 3u);
//(4)将 FLASH_CR 寄存器中的 STRT 位置 1,开始扇区擦除
FLASH->CR |= FLASH_CR_STRT;
//(5)等待 FLASH_SR 寄存器中的 BSY 位清零,等待擦除操作完成
while( (FLASH->SR & FLASH_SR_BSY) != 0U);
FLASH->CR &= ~FLASH_CR_PER;
return 0; //成功返回
}
//======================================================================
//函数名称:flash_write
//函数返回:函数执行状态:0=正常;1=异常。
//参数说明:sect:扇区号(范围取决于实际芯片,例如 STM32L433:0~127,每扇区2KB)
// offset:写入扇区内部偏移地址(0~2044,要求为0,4,8,12,......)
// N:写入字节数目(4~2048,要求为4,8,12,......)
// buf:源数据缓冲区首地址
//功能概要:将buf开始的N字节写入到flash存储器的sect扇区的 offset处
//编程参考:暂无
//=======================================================================
uint8_t flash_write(uint16_t sect,uint16_t offset,uint16_t N,uint8_t *buf)
{
//(1)定义变量
uint16_t i;
//(2)清除之前的编程导致的所有错误标志位
FLASH->SR &= 0xFFFFFFUL;
//(3.1)写入字节数后会跨扇区
if(offset+N>MCU_SECTORSIZE)
{
//(3.1.1)先写入第一个扇区
flash_write(sect,offset,MCU_SECTORSIZE-offset,buf);
//(3.1.2)再写入第二个扇区
flash_write(sect+1,0,N-(MCU_SECTORSIZE-offset),buf+(MCU_SECTORSIZE-offset));
}
//(3.2)写入字节数不会跨扇区
else
{
uint8_t data[MCU_SECTORSIZE]; //存储当前扇区的全部值
flash_read_logic(data,sect,0,MCU_SECTORSIZE); //将当前扇区的全部值读入数组中
//将要写入的数据依照对应位置写入数组中
for(i = 0;i<N;i++)
{
data[offset+i] = buf[i];
}
//擦除扇区
//flash_erase(sect);
//将数组写入扇区
if(flash_Best(sect,0,MCU_SECTORSIZE,data)!=0)
return 1;
}
//(4)等待写入操作完成
while( (FLASH->SR & FLASH_SR_BSY) != 0U);
return 0; //成功执行
}
//==========================================================================
//函数名称:flash_write_physical
//函数返回:函数执行状态:0=正常;非0=异常。
//参数说明: addr:目标地址,要求为4的倍数且大于Flash首地址
// (例如:0x08000004,Flash首地址为0x08000000)
// cnt:写入字节数目(8~512)
// buf:源数据缓冲区首地址
//功能概要:flash写入操作
//编程参考:暂无
//==========================================================================
uint8_t flash_write_physical(uint32_t addr,uint16_t N,uint8_t buf[])
{
//(1)定义变量。sect-扇区号,offset-扇区地址
uint16_t sect; //扇区号
uint16_t offset; // 偏移地址
//(2)变量赋值,将物理地址转换为逻辑地址(扇区和偏移量)
sect = (addr-MCU_FLASH_ADDR_START)/MCU_SECTORSIZE;
offset = addr-(sect*MCU_SECTORSIZE)-MCU_FLASH_ADDR_START;
//(3)调用写入函数写入数据
flash_write(sect,offset,N,buf);
//(4)等待写入操作完成
while( (FLASH->SR & FLASH_SR_BSY) != 0U);
return 0; //成功执行
}
//======================================================================
//函数名称:flash_read_logic
//函数返回:无
//参数说明:dest:读出数据存放处(传地址,目的是带出所读数据,RAM区)
// sect:扇区号(范围取决于实际芯片,例如 STM32L433:0~127,每扇区2KB)
// offset:扇区内部偏移地址(0~2024,要求为0,4,8,12,......)
// N:读字节数目(4~2048,要求为4,8,12,......)//
//功能概要:读取flash存储器的sect扇区的 offset处开始的N字节,到RAM区dest处
//编程参考:暂无
//=======================================================================
void flash_read_logic(uint8_t *dest,uint16_t sect,uint16_t offset,uint16_t N)
{
//(1)定义变量。src-读取的数据的地址
uint8_t *src;
//(2)变量赋值。通过扇区号和偏移量计算出逻辑地址
src=(uint8_t *)(FLASH_BASE+sect*FLASH_PAGE_SIZE+offset);
//(3)读出数据
memcpy(dest,src,N);
}
//======================================================================
//函数名称:flash_read_physical
//函数返回:无
//参数说明:dest:读出数据存放处(传地址,目的是带出所读数据,RAM区)
// addr:目标地址,要求为4的倍数(例如:0x00000004)
// N:读字节数目(0~1020,要求为4,8,12,......)
//功能概要:读取flash指定地址的内容
//编程参考:暂无
//======================================================================
void flash_read_physical(uint8_t *dest,uint32_t addr,uint16_t N)
{
//(1)定义变量。src-读取的数据的地址
uint8_t *src;
//(2)变量赋值。直接使用物理地址
src=(uint8_t *)addr;
//(3)读出数据
memcpy(dest,src,N);
}
//======================================================================
//函数名称:flash_protect
//函数返回:无
//参数说明:M:待保护的扇区号
//功能概要:flash保护操作
//编程参考:暂无
//======================================================================
void flash_protect(uint8_t M)
{
//(1)定义变量。temp-配置所用值
uint32_t temp;
//(2)变量赋值。
temp = M|((M+1)<<16);
//(3)对保护区进行锁定
if((FLASH->CR & FLASH_CR_OPTLOCK) != 0U)
{
FLASH->OPTKEYR = (uint32_t)FLASH_OPTKEY1;
FLASH->OPTKEYR = (uint32_t)FLASH_OPTKEY2;
}
//(4)等待锁定成功
while((FLASH->CR & FLASH_CR_OPTLOCK) != 0U);
//(5)等待 FLASH_SR 寄存器中的 BSY 位清零,等待擦除操作完成
while( (FLASH->SR & FLASH_SR_BSY) != 0U);
//(6)配置相关寄存器
FLASH->WRP1AR &= 0x0;
FLASH->WRP1AR |= temp;
FLASH->CR |= FLASH_CR_OPTSTRT;
//(7)等待 FLASH_SR 寄存器中的 BSY 位清零,等待擦除操作完成
while( (FLASH->SR & FLASH_SR_BSY) != 0U);
FLASH->CR &= ~FLASH_CR_OPTSTRT;
}
//======================================================================
//函数名称:flash_unprotect
//函数返回:无
//参数说明:M:待解保护的扇区号
//功能概要:flash解保护操作
//说明:
//编程参考:暂无
//======================================================================
void flash_unprotect(uint8_t M)
{
//(1)定义变量。temp-配置所用值
uint32_t temp;
//(2)变量赋值。
temp = 0xff00ffff;
//(3)对保护区进行锁定
if((FLASH->CR & FLASH_CR_OPTLOCK) != 0U)
{
FLASH->OPTKEYR = (uint32_t)FLASH_OPTKEY1;
FLASH->OPTKEYR = (uint32_t)FLASH_OPTKEY2;
}
//(4)等待 FLASH_SR 寄存器中的 BSY 位清零,等待操作完成
while( (FLASH->SR & FLASH_SR_BSY) != 0U);
//(5)配置相关寄存器
FLASH->WRP1AR &= 0x0;
FLASH->WRP1AR |= temp;
FLASH->CR |= FLASH_CR_OPTSTRT;
//(6)等待 FLASH_SR 寄存器中的 BSY 位清零,等待操作完成
while( (FLASH->SR & FLASH_SR_BSY) != 0U);
FLASH->CR &= ~FLASH_CR_OPTSTRT;
}
//======================================================================
//函数名称:flash_isempty
//函数返回:1=目标区域为空;0=目标区域非空。
//参数说明:所要探测的flash区域初始地址
//功能概要:flash判空操作
//编程来源:暂无
//======================================================================
uint8_t flash_isempty(uint16_t sect,uint16_t N)
{
//(1)定义变量flag-操作成功标志,src-目标地址,dest[]-暂存数据
uint16_t i,flag;
uint8_t dest[N];
uint8_t *src;
//(2)变量赋值并读取数据
flag = 1;
src=(uint8_t *)(FLASH_BASE+sect*FLASH_PAGE_SIZE);
memcpy(dest,src,N);
//(3)判断区域内数据是否为空
for(i = 0; i<N; i++) //遍历区域内字节
{
if(dest[i]!=0xff) //非空
{
flag=0;
break;
}
}
return flag;
}
//========================================================================
//函数名称:flashCtl_isSectorProtected
//函数返回:1=扇区被保护;0=扇区未被保护
//参数说明:所要检测的扇区
//功能概要:判断flash扇区是否被保护
//编程参考:暂无
//=========================================================================
uint8_t flash_isSectorProtected(uint16_t sect)
{
//(1)定义变量。STRT-扇区开始号,END-扇区结束号,temp-暂存值
uint8_t STRT,END;
uint32_t temp;
//(2)查看扇区是否被保护
temp = FLASH->WRP1AR;
STRT = temp;
END = temp>>16;
if(sect>=STRT && sect<END)
return 1;
//(3)查看扇区是否被保护
temp = FLASH->WRP1BR;
STRT = temp;
END = temp>>16;
if(sect>=STRT && sect<END)
return 1;
return 0;
}
//----------------------以下为内部函数存放处----------------------------
//======================================================================
//函数名称:flash_write_DoubleWord
//函数返回:0-成功 1-失败
//参数说明:addr:目标地址,要求为4的倍数且大于Flash首地址
// (例如:0x08000004,Flash首地址为0x08000000)
// data:写入的双字
//功能概要:Flash双字写入操作(STM32L433每次只能实现双字写入,先写低位字,再写高位字)
//编程参考:暂无
//======================================================================
uint8_t flash_write_DoubleWord(uint32_t addr,uint32_t data_l,uint32_t data_h)
{
//(1)清数据缓冲区
if((FLASH->ACR & FLASH_ACR_DCEN) != 0U)
{
FLASH->ACR &= ~FLASH_ACR_DCEN;
}
//(2)使能Flash即时编程
FLASH->CR |= FLASH_CR_PG;
//(3.1)先写入低位字
*(__IO uint32_t*)addr = data_l;
//(3.2)再写入高位字
*(__IO uint32_t*)(addr+4U) = data_h;
//(4)禁止Flash即时编程
FLASH->CR &= ~FLASH_CR_PG;
return 0; //返回成功
}
#endif
//======================================================================
//函数名称:flash_Best
//函数返回:0-成功 1-失败
//参数说明:sect:待写入扇区号
// offset:待写入数据位置的偏移地址
// N:待写入数据字节数
// buf:待写入数据的首地址
//功能概要:首位地址都对齐的情况下的数据写入
//编程参考:暂无
//======================================================================
uint8_t flash_Best(uint16_t sect,uint16_t offset,uint16_t N,uint8_t *buf)
{
//(1)定义变量。temp_l,temp_h,addr,i
uint32_t temp_l,temp_h;
uint32_t addr;
uint16_t i;
//(2)等待 FLASH_SR 寄存器中的 BSY 位清零,等待操作完成
while( (FLASH->SR & FLASH_SR_BSY) != 0U);
//(3)计算双字写入绝对地址
addr = (uint32_t)(FLASH_BASE+sect*FLASH_PAGE_SIZE+offset);
//(4)循环写入双字,每8个数写一次
for(i = 0; i < N; i+=8)
{
//(4.1)低位字赋值
temp_l = (uint32_t)((buf[i])|(buf[i+1]<<8)|(buf[i+2]<<16)|(buf[i+3]<<24));
//(4.2)高位字赋值
temp_h = (uint32_t)((buf[i+4])|(buf[i+5]<<8)|(buf[i+6]<<16)|(buf[i+7]<<24));
//(4.3)在绝对地址(addr+i),实现双字写入
flash_write_DoubleWord((addr+i),temp_l,temp_h);
}
//(5)等待 FLASH_SR 寄存器中的 BSY 位清零,等待操作完成
while( (FLASH->SR & FLASH_SR_BSY) != 0U);
return 0;
}
结果如下:
如果写入成功,将显示“Erase the text!”
结论:如果没有擦除,不能写入新数据,因为Flash 存储器芯片或微控制器具有硬件级别的保护机制,防止在没有擦除的情况下进行写入。这种保护机制可能会导致写入操作在硬件级别上失败,即使软件层面的函数调用返回成功。
2、在ADC实验中,结合热敏电阻,分别通过触摸芯片表面和热敏电阻,引起A/D值变化,显示芯片内部温度和当前温度。
main.c中通过Regression_Ext_Temp和Regression_MCU_Temp函数将获得的环境和芯片内部温度AD值转化为实际温度,并添加相应的输出
完整代码:
#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)
{
//(1)======启动部分(开头)==========================================
//(1.1)声明main函数使用的局部变量
uint32_t mMainLoopCount; //主循环次数变量
uint16_t num_AD2;
uint16_t num_AD3;
uint16_t temp_AD2;
uint16_t temp_AD3;
//(1.2)【不变】关总中断
DISABLE_INTERRUPTS;
//(1.3)给主函数使用的局部变量赋初值
mMainLoopCount=0; //主循环次数变量
//(1.4)给全局变量赋初值
//(1.5)用户外设模块初始化
gpio_init(LIGHT_BLUE,GPIO_OUTPUT,LIGHT_ON); //初始化蓝灯
adc_init(ADC_CHANNEL_1,AD_DIFF); //初始化ADC通道1,
adc_init(ADC_CHANNEL_15,AD_DIFF); //初始化ADC通道15
adc_init(ADC_CHANNEL_TEMPSENSOR,AD_SINGLE); //初始化ADC通道:内部温度
emuart_init(UART_User,115200);
//(1.6)使能模块中断
uart_enable_re_int(UART_User);
//(1.7)【不变】开总中断
ENABLE_INTERRUPTS;
printf("------------------------------------------------------\n");
printf("金葫芦提示: \n");
printf("(1)目的:ADC单端输入与差分输入测试 \n");
printf("(2)单端:内部温度传感器,通道号17,无需引脚对应 \n");
printf(" 差分:GEC引脚47、46(通道1、2) \n");
printf(" GEC引脚12、11(通道15、16 \n");
printf("(3)测试方法:单端:手摸芯片表面,A/D值增大,不要摸 \n");
printf(" 到引脚,静电可能损坏芯片 \n");
printf(" 差分:将引脚47接地、46接3.3V,观察通道1情况\n");
printf(" 将引脚46接地、47接3.3V,观察通道1情况\n");
printf(" 类似方法,观察通道15 \n");
printf("------------------------------------------------------\n");
printf("32106100061 CQL的ADC实验\n");
//(1)======启动部分(结尾)==========================================
//(2)======主循环部分(开头)========================================
for(;;) //for(;;)(开头)
{
//(2.1)主循环次数变量+1
mMainLoopCount++;
//(2.2)未达到主循环次数设定值,继续循环
//延时1秒
if (mMainLoopCount<=3000000) continue;
//(2.3)达到主循环次数设定值,执行下列语句,进行灯的亮暗处理
//(2.3.1)清除循环次数变量
mMainLoopCount=0;
//(2.3.2)如灯状态标志mFlag为'L',灯的闪烁次数+1并显示,改变灯状态及标志
num_AD2 = adc_ave(ADC_CHANNEL_15,8);
num_AD3 = adc_ave(ADC_CHANNEL_TEMPSENSOR,8);
temp_AD2 =Regression_Ext_Temp(num_AD2); //环境温度AD值转为实际温度
temp_AD3=Regression_MCU_Temp(num_AD3); //芯片温度AD值转为实际温度
printf("环境温度的A/D值: %d\r\n",num_AD2);
printf("环境温度:%d\r\n",temp_AD2);
printf("内部温度传感器的A/D值:%d\r\n\n",num_AD3);
printf("内部温度:%d\t\n",temp_AD3);
Delay_ms(1000);
} //for(;;)结尾
//(2)======主循环部分(结尾)========================================
} //main函数(结尾)
//======以下为主函数调用的子函数===========================================
//======================================================================
//函数名称:Delay_ms
//函数返回:无
//参数说明:无
//功能概要:延时 - 毫秒级
//======================================================================
void Delay_ms(uint16_t u16ms)
{
uint32_t u32ctr;
for(u32ctr = 0; u32ctr < 8000*u16ms; u32ctr++)
{
__ASM("NOP");
}
}
//======================================================================
//功能概要:连续判断三次GPIO的输入引脚,大部分为0,则认为有触摸
//参数说明:GPIO引脚
//函数返回:1:有触摸,0:无触摸
//原理概要:当GPIO引脚被定义为无上下拉输入功能时,容易收到外界干扰,本程序
// 把这个特性转为有用的功能,由于人体相当于一个大电阻,手触摸这个
// 引脚会使得引脚状态发生随机性改变,利用这种变化可以被视为有触摸,
// 实现了无触摸功能引脚的触摸功能
//======================================================================
//============================================================================
//函数名称:Regression_Ext_Temp
//功能概要:将读到的环境温度AD值转换为实际温度
//参数说明:tmpAD:通过adc_read函数得到的AD值
//函数返回:实际温度值
//============================================================================
float Regression_Ext_Temp(uint16_t tmpAD)
{
float Vtemp,Rtemp,temp;
if(tmpAD<=72)
{
return -274;
}
Vtemp = (tmpAD*3300.0)/4096;
Rtemp = Vtemp/(3300.0 - Vtemp)*10000.0;
temp = (1/(log(Rtemp/10000.0)/3950.0 + (1/(273.15 + 25)))) - 273.15 + 0.5;
return temp;
}
//============================================================================
//函数名称:Regression_MCU_Temp
//功能概要:将读到的mcu温度AD值转换为实际温度
//参数说明:mcu_temp_AD:通过adc_read函数得到的AD值
//函数返回:实际温度值
//============================================================================
float Regression_MCU_Temp(uint16_t mcu_temp_AD)
{
float mcu_temp_result;
mcu_temp_result=(float)(55+(100*((float)(mcu_temp_AD) - AD_CAL1))/(AD_CAL2 - AD_CAL1));
return mcu_temp_result;
}
//========================================================================
/*
知识要素:
(1)main.c是一个模板,该文件所有代码均不涉及具体的硬件和环境,通过调用构件
实现对硬件的干预。
(2)本文件中对宏GLOBLE_VAR进行了定义,所以在包含"includes.h"头文件时,会定
义全局变量,在其他文件中包含"includes.h"头文件时,
编译时会自动增加extern
*/
触摸芯片表面和热敏电阻时:
环境温度上升