嵌入式实验7

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
*/

触摸芯片表面和热敏电阻时: 

环境温度上升

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值