历史上的今天
返回首页

历史上的今天

今天是:2025年08月15日(星期五)

正在发生

2019年08月15日 | STM32学习笔记一一RTC实时时钟

2019-08-15 来源:eefocus

1. 简述

STM32 的实时时钟(RTC)是一个独立的定时器。 STM32 的 RTC 模块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的功能。修改计数器的值可以重新设置系统当前的时间和日期。


RTC 模块和时钟配置系统 (RCC_BDCR 寄存器)是在后备区域,即在系统复位或从待机模式唤醒后 RTC 的设置和时间维持不变。但是在系统复位后,会自动禁止访问后备寄存器和 RTC,以防止对后备区域 (BKP) 的意外写操作。所以在要设置时间之前, 先要取消备份区域(BKP)写保护。


在这里插入图片描述

RTC 由两个主要部分组成(参见上图), 第一部分(APB1 接口)用来和 APB1 总线相连。此单元还包含一组 16 位寄存器,可通过 APB1 总线对其进行读写操作。 APB1 接口由 APB1 总线时钟驱动,用来与 APB1 总线连接。


另一部分 (RTC 核心) 由一组可编程计数器组成,分成两个主要模块。第一个模块是 RTC 的预分频模块,它可编程产生 1 秒的 RTC 时间基准 TR_CLK。 RTC 的预分频模块包含了一个 20 位的可编程分频器 (RTC 预分频器)。如果在 RTC_CR 寄存器中设置了相应的允许位,则在每个TR_CLK 周期中 RTC 产生一个中断(秒中断)。第二个模块是一个 32 位的可编程计数器,可被初始化为当前的系统时间,一个 32 位的时钟计数器,按秒钟计算,可以记录 4294967296 秒,约合 136 年左右。


RTC 还有一个闹钟寄存器 RTC_ALR,用于产生闹钟。系统时间按 TR_CLK 周期累加并与存储在 RTC_ALR 寄存器中的可编程时间相比较,如果 RTC_CR 控制寄存器中设置了相应允许位,比较匹配时将产生一个闹钟中断。RTC 内核完全独立于 RTC APB1 接口,而软件是通过 APB1 接口访问 RTC 的预分频值、计数器值和闹钟值的。但是相关可读寄存器只在 RTC APB1 时钟进行重新同步的 RTC 时钟的上升沿被更新, RTC 标志也是如此。这就意味着,如果 APB1 接口刚刚被开启之后,在第一次的内部寄存器更新之前,从 APB1 上读取的 RTC 寄存器值可能被破坏了(通常读到 0)。因此,若在读取 RTC 寄存器曾经被禁止的 RTC APB1 接口,软件首先必须等待 RTC_CRL 寄存器的 RSF位(寄存器同步标志位, bit3)被硬件置 1。


2. RTC 寄存器介绍

2.1 RTC 的控制寄存器——RTC_CRH 寄存器

在这里插入图片描述

该寄存器用来控制中断的。


2.2 RTC 的控制寄存器——RTC_CRL 寄存器

在这里插入图片描述

RTC 用到的是该寄存器的 0、 3~5 这几个位,第 0 位是秒钟标志位,我们在进入闹钟中断的时候,通过判断这位来决定是不是发生了秒钟中断。然后必须通过软件将该位清零(写 0)。第 3 位为寄存器同步标志位,我们在修改控制寄存器 RTC_CRH/CRL 之前,必须先判断该位,是否已经同步了,如果没有则等待同步,在没同步的情况下修 RTC_CRH/CRL 的值是不行的。第 4 位为配置标位,在软件修改 RTC_CNT/RTC_ALR/RTC_PRL 的值的时候,必须先软件置位该位,以允许进入配置模式。第 5 位为 RTC 操作位,该位由硬件操作,软件只读。通过该位可以判断上次对 RTC 寄存器的操作是否完成,如果没有,我们必须等待上一次操作结束才能开始下一次操作。


2.3 RTC 预分频装载寄存器——RTC_PRLH 寄存器

这两个寄存器用来配置 RTC 时钟的分频数的,比如我们使用外部 32.768K 的晶振作为时钟的输入频率,那么我们要设置这两个寄存器的值为 32767,以得到一秒钟的计数频率。


在这里插入图片描述

2.4 RTC 预分频装载寄存器——RTC_PRLL 寄存器


在这里插入图片描述

2.5 RTC 预分频器余数寄存器——RTC_DIVH 寄存器

在这里插入图片描述

2.6 RTC 预分频器余数寄存器——RTC_DIVH 寄存器

在这里插入图片描述

这两个寄存器的作用就是用来获得比秒钟更为准确的时钟,比如可以得到 0.1 秒,或者 0.01 秒等。该寄存器的值自减的,用于保存还需要多少时钟周期获得一个秒信号。在一次秒钟更新后,由硬件重新装载。


2.7 RTC 计数器寄存器——RTC_CNT 寄存器

该寄存器由 2 个 16 位的寄存器组成 RTC_CNTH 和 RTC_CNTL,总共 32 位,用来记录秒钟值(一般情况下)。在修改这个寄存器的时候要先进入配置模式。

在这里插入图片描述

2.8 RTC 计数器寄存器——RTC 闹钟寄存器

该寄存器也是由 2 个 16 位的寄存器组成 RTC_ALRH 和 RTC_ALRL。总共也是 32 位,用来标记闹钟产生的时间(以秒为单位),如果 RTC_CNT 的值与 RTC_ALR 的值相等,并使能了中断的话,会产生一个闹钟中断。该寄存器的修改也要进入配置模式才能进行。


在这里插入图片描述

3. 备份寄存器介绍

备份寄存器是 42 个 16 位的寄存器(Mini 开发板就是大容量的),可用来存储 84 个字节的用户应用程序数据。他们处在备份域里,当 VDD 电源被切断,他们仍然由 VBAT 维持供电。即使系统在待机模式下被唤醒,或系统复位或电源复位时,他们也不会被复位。


复位后,对备份寄存器和 RTC 的访问被禁止,并且备份域被保护以防止可能存在的意外的

写操作。执行以下操作可以使能对备份寄存器和 RTC 的访问:


(1)通过设置寄存器 RCC_APB1ENR 的 PWREN 和 BKPEN 位来打开电源和后备接口的时钟;


(2)电源控制寄存器 (PWR_CR) 的 DBP 位来使能对后备寄存器和 RTC 的访问。


一般用 BKP 来存储 RTC 的校验值或者记录一些重要的数据,相当于一个 EEPROM,不过这个 EEPROM 并不是真正的 EEPROM,而是需要电池来维持它的数据。


在这里插入图片描述

RTC 的时钟源选择及使能设置都是通过这个寄存器来实现的,所以我们在 RTC 操作之前先要通过这个寄存器选择 RTC 的时钟源,然后才能开始其他的操作。


4. RTC 配置步骤

(1) 使能电源时钟和备份区域时钟


RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);


(2) 取消备份区写保护


PWR_BackupAccessCmd(ENABLE); //使能 RTC 和后备寄存器访问


(3) 复位备份区域,开启外部低速振荡器。


BKP_DeInit();//复位备份区域


(4) 选择 RTC 时钟,并使能


RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //选择 LSE 作为 RTC 时钟(RCC_RTCCLKSource_LSI 和 RCC_RTCCLKSource_HSE_Div128)

RCC_RTCCLKCmd(ENABLE); //使能 RTC 时钟


(5) 设置 RTC 的分频,以及配置 RTC 时钟


在开启了 RTC 时钟之后,我们要做的是设置 RTC 时钟的分频数,通过 RTC_PRLH 和RTC_PRLL 来设置,然后等待 RTC 寄存器操作完成,并同步之后,设置秒钟中断。然后设置 RTC 的允许配置位(RTC_CRH 的 CNF 位),设置时间(其实就是设置RTC_CNTH 和 RTC_CNTL两个寄存器)。


RTC_EnterConfigMode();/// 允许配置

RTC_ExitConfigMode();//退出配置模式,更新配置

void RTC_SetPrescaler(uint32_t PrescalerValue);

void RTC_ITConfig(uint16_t RTC_IT, FunctionalState NewState);//RTC_ITConfig(RTC_IT_SEC, ENABLE); //使能 RTC 秒中断

void RTC_SetCounter(uint32_t CounterValue)最后在配置完成之后


(6) 更新配置,设置 RTC 中断分组


设置完时钟之后,我们将配置更新同时退出配置模式,这里还是通过 RTC_CRH 的 CNF

来实现。


RTC_ExitConfigMode();//退出配置模式,更新配置


在退出配置模式更新配置之后我们在备份区域 BKP_DR1 中写入 0X5050 代表我们已经初始化过时钟了,下次开机(或复位)的时候,先读取 BKP_DR1 的值,然后判断是否是 0X5050 来决定是不是要配置。接着我们配置 RTC 的秒钟中断,并进行分组。


void BKP_WriteBackupRegister(uint16_t BKP_DR, uint16_t Data);//往备份区域写用户数据

uint16_t BKP_ReadBackupRegister(uint16_t BKP_DR);//读取备份区域指定寄存器


(7) 编写中断服务函数


流程图:


在这里插入图片描述

5. 程序实现

5.1 初始化

u8 RTC_Init(void)

{

//检查是不是第一次配置时钟

u8 temp=0;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); //使能PWR和BKP外设时钟   

PWR_BackupAccessCmd(ENABLE); //使能后备寄存器访问  

if (BKP_ReadBackupRegister(BKP_DR1) != 0x5050) //从指定的后备寄存器中读出数据:读出了与写入的指定数据不相乎

{


BKP_DeInit(); //复位备份区域

RCC_LSEConfig(RCC_LSE_ON); //设置外部低速晶振(LSE),使用外设低速晶振

while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) //检查指定的RCC标志位设置与否,等待低速晶振就绪

{

temp++;

delay_ms(10);

}

if(temp>=250)

return 1;//初始化时钟失败,晶振有问题     

RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //设置RTC时钟(RTCCLK),选择LSE作为RTC时钟    

RCC_RTCCLKCmd(ENABLE); //使能RTC时钟  

RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成

RTC_WaitForSynchro(); //等待RTC寄存器同步  

RTC_ITConfig(RTC_IT_SEC, ENABLE); //使能RTC秒中断

RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成

RTC_EnterConfigMode();/// 允许配置

RTC_SetPrescaler(32767); //设置RTC预分频的值

RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成

RTC_Set(1972,1,2,1,1,1);  //设置时间

RTC_ExitConfigMode(); //退出配置模式  

BKP_WriteBackupRegister(BKP_DR1, 0X5050); //向指定的后备寄存器中写入用户程序数据

}

else//系统继续计时

{


RTC_WaitForSynchro(); //等待最近一次对RTC寄存器的写操作完成

RTC_ITConfig(RTC_IT_SEC, ENABLE); //使能RTC秒中断

RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成

}

RTC_NVIC_Config();//RCT中断分组设置          

RTC_Get();//更新时间

return 0; //ok


}


static void RTC_NVICConfig(void)

{

    NVIC_InitTypeDef NVIC_InitStructure;

NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn; //RTC全局中断

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级1位,从优先级3位

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //先占优先级0位,从优先级4位

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能该通道中断

NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

}


中断服务函数:


void RTC_IRQHandler(void)

{  

if (RTC_GetITStatus(RTC_IT_SEC) != RESET)//秒钟中断

{

RTC_Get();//更新时间   

  }

if(RTC_GetITStatus(RTC_IT_ALR)!= RESET)//闹钟中断

{

RTC_ClearITPendingBit(RTC_IT_ALR); //清闹钟中断      

  }    

RTC_ClearITPendingBit(RTC_IT_SEC|RTC_IT_OW); //清闹钟中断

RTC_WaitForLastTask();            

}


5.2 RTC部分实现

闰年判断:


//判断是否是闰年函数

//月份   1  2  3  4  5  6  7  8  9  10 11 12

//闰年   31 29 31 30 31 30 31 31 30 31 30 31

//非闰年 31 28 31 30 31 30 31 31 30 31 30 31

//输入:年份

//输出:该年份是不是闰年.1,是.0,不是

u8 Is_Leap_Year(u16 year)

{   

if(year%4==0) //必须能被4整除

if(year%100==0) 

if(year%400==0)

return 1;//如果以00结尾,还要能被400整除    

else 

return 0;   

}

else 

return 1;   

}

else 

return 0;

}



时钟设置:


//设置时钟

//把输入的时钟转换为秒钟

//以1970年1月1日为基准

//1970~2099年为合法年份

//返回值:0,成功;其他:错误代码.

//月份数据表


u8 const table_week[12]={0,3,3,6,1,4,6,2,5,0,3,5}; //月修正数据表   

//平年的月份日期表

const u8 mon_table[12]={31,28,31,30,31,30,31,31,30,31,30,31};


u8 RTC_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec)

{

u16 t;

u32 seccount=0;

if(syear<1970||syear>2099)

return 1;    

for(t=1970;t {

if(Is_Leap_Year(t))

seccount += 31622400;//闰年的秒钟数

else 

seccount += 31536000;   //平年的秒钟数

}

smon -= 1;//月份从1开始,数组从0开始计数

for(t=0;t {

seccount += (u32)mon_table[t] * 86400;//月份秒钟数相加

if(Is_Leap_Year(syear)&&t==1)

seccount += 86400;//闰年2月份增加一天的秒钟数    

}

seccount += (u32)(sday-1) * 86400;//把前面日期的秒钟数相加(整天数) 

seccount += (u32)hour * 3600;//小时秒钟数

    seccount += (u32)min * 60; //分钟秒钟数

seccount += sec;//最后的秒钟加上去


RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); //使能PWR和BKP外设时钟  

PWR_BackupAccessCmd(ENABLE); //使能RTC和后备寄存器访问 

RTC_SetCounter(seccount); //设置RTC计数器的值


RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成 

RTC_Get();

return 0;     

}


得到当前时间:


//得到当前的时间

//返回值:0,成功;其他:错误代码.

u8 RTC_Get(void)

{

static u16 daycnt=0;

u32 timecount=0; 

u32 temp=0;

u16 temp1=0;

    timecount = RTC_GetCounter();  

//timecount = 86400*4+88;

  temp = timecount / 86400;   //得到天数(秒钟数对应的)

if(daycnt!=temp)//超过一天了

{   

daycnt = temp;

temp1 = 1970; //从1970年开始

while(temp>=365)

{  

if(Is_Leap_Year(temp1))//是闰年

{

if(temp>=366)

temp -= 366;//减去一闰年,还剩下的天数

else 

{

temp1 ++;

break;

}  

}

else 

temp -= 365;   //减去一平年 ,还剩下的天数

temp1 ++;  

}   

calendar.w_year = temp1;//得到年份

temp1=0;

while(temp>=28)//28天,超过了最小的一个月

{

if(Is_Leap_Year(calendar.w_year)&&temp1==1)//当年是不是闰年/2月份

{

if(temp>=29)

temp -= 29;//闰年的秒钟数

else 

break; 

}

else 

{

if(temp>=mon_table[temp1])

temp -= mon_table[temp1];//平年

else 

break;

}

temp1++;  

}

calendar.w_month = temp1+1; //得到月份

calendar.w_date = temp+1;  //得到日期 

}

temp = timecount%86400;      //得到秒钟数       

calendar.hour = temp/3600;      //小时

calendar.min = (temp%3600)/60; //分钟

calendar.sec = (temp%3600)%60; //秒钟

calendar.week = RTC_Get_Week(calendar.w_year,calendar.w_month,calendar.w_date);//获取星期 

return 0;

}


得到星期几:


//获得现在是星期几

//功能描述:输入公历日期得到星期(只允许1901-2099年)

//输入参数:公历年月日 

//返回值:星期号  

u8 RTC_GetWeek(u16 year,u8 month,u8 day)

{

u16 temp2;

u8 yearH,yearL;

yearH = year/100;

yearL = year%100; 

// 如果为21世纪,年份数加100  

if (yearH>19)

yearL += 100;

// 所过闰年数只算1900年之后的  

temp2 = yearL+yearL/4;

temp2 = temp2%7; 

temp2 = temp2+day+table_week[month-1];

if (yearL%4==0&&month<3)

temp2--;

return(temp2%7);

}   


对于星期如何转换,可参考如下链接:

1.RTC-由年月日计算星期几


2.基姆拉尔森计算公式


6. 附录:

STM32 时钟树:



参考:


1.[原子教程库函数实现]


2.STM32开发 – RTC详解


推荐阅读

史海拾趣

Axiomtek公司的发展小趣事

由于Axiomtek公司的发展涉及众多方面,并且具体的内部故事和详细事实可能不为公众所知,因此我无法直接提供5个具体的故事。但我可以根据公开资料,概括性地描述Axiomtek公司在电子行业中的发展历程,以及可能促成其发展的几个关键因素。

Axiomtek,也称为艾讯科技,自1990年在台湾成立以来,凭借其创新的设计、高质量的品质保证和高客户满意度的服务态度,逐步发展成为世界工业计算机领域的领先设计者和制造商。以下是根据公开资料概括的Axiomtek公司发展的几个关键阶段和因素:

一、创业初期:创新与技术的奠基

在创业初期,Axiomtek由一群充满创新精神和干劲的资深工程师创立。他们凭借对计算机技术的深刻理解和对工业需求的敏锐洞察,开始研发并生产一系列具有创新性的工业计算机产品。这些产品不仅满足了当时市场的迫切需求,还以其卓越的性能和稳定性赢得了客户的广泛认可。

二、研发与制造能力的不断提升

随着市场的不断扩大和竞争的加剧,Axiomtek意识到只有不断提升研发与制造能力,才能在激烈的市场竞争中立于不败之地。因此,公司投入大量资源用于研发新技术和新产品,并建立了完善的制造体系,以确保产品的高质量和稳定性。同时,Axiomtek还积极与全球知名的供应商和合作伙伴建立战略合作关系,共同推动工业计算机领域的技术进步和产业发展。

三、全球化布局与市场拓展

为了进一步扩大市场份额和提高品牌影响力,Axiomtek开始实施全球化战略。公司在全球多个国家和地区设立了分支机构,并建立了完善的销售和服务网络。通过这些分支机构,Axiomtek能够更好地了解当地市场需求和客户需求,提供更加贴近市场的产品和服务。同时,公司还积极参加各种国际展览和交流活动,与全球客户建立更加紧密的合作关系。

四、持续创新与技术升级

在快速发展的电子行业中,技术创新是保持竞争力的关键。Axiomtek始终坚持以创新为核心的发展战略,不断投入研发资源,推动技术升级和产品创新。公司不仅关注现有产品的优化和改进,还积极探索新的应用领域和市场机会,开发具有前瞻性的新产品和解决方案。这些创新成果不仅增强了Axiomtek的市场竞争力,还为公司的持续发展奠定了坚实的基础。

五、品质管理与客户服务的持续优化

品质和客户满意度一直是Axiomtek非常重视的方面。公司建立了严格的质量管理体系,从原材料采购到产品生产、测试和交付等各个环节都进行严格把控,确保产品的高品质。同时,Axiomtek还注重提升客户服务水平,通过提供专业的技术支持和售后服务,赢得了客户的信任和好评。这种以客户为中心的经营理念不仅提升了公司的品牌形象,还为公司赢得了更多的商业机会。

这些只是根据公开资料概括的Axiomtek公司发展的几个关键方面,具体的故事和细节可能需要根据公司内部的资料和档案进行进一步的挖掘和整理。但无论如何,Axiomtek作为电子行业中的佼佼者,其发展历程无疑是一个充满创新、挑战和机遇的传奇故事。

FEMA Electronics Corporation公司的发展小趣事

FEMA的创始人李明(化名)是一位资深的电子工程师,他在一次与客户的交流中,发现了市场对高质量电子元件的迫切需求。于是,他毅然决定创办FEMA,专注于研发和生产高性能的电子元器件。创业初期,公司面临着资金短缺、技术瓶颈等重重挑战。然而,李明凭借坚定的信念和不懈的努力,成功攻克了技术难关,并与多家知名企业建立了合作关系,为公司的发展奠定了坚实的基础。

Amperite Co公司的发展小趣事

随着全球化的加速推进,FEMA意识到要想在更广阔的市场上取得更大的发展,必须实施国际化战略。于是,公司开始积极拓展海外市场,与多个国家和地区的客户建立了合作关系。同时,FEMA还加强了与国际先进企业的技术交流和合作,不断吸收和借鉴国际先进的经验和技术。这些举措为公司的国际化发展提供了有力支持,使FEMA的产品在国际市场上赢得了更广泛的认可。

Conditioning Semiconductor Devices Corp公司的发展小趣事

为了进一步提升技术水平和扩大市场份额,CSDC积极寻求与国际半导体巨头的合作。通过与这些公司的技术交流和合作研发,CSDC不仅获得了先进的技术支持,还成功打入了国际市场。这一合作不仅提升了CSDC的品牌影响力,也为其带来了更多的商业机会。

ALCOA公司的发展小趣事

在20世纪的后半叶,ALCOA继续在技术上取得重大突破。例如,在40年代,公司采用N-40(Niagara)50kA中心下料预焙阳极电解槽技术为政府建造了铝冶炼厂。此外,公司还不断扩大海外业务,建立了全球性的生产和销售网络。这种全球布局使得ALCOA能够更好地满足不同地区的市场需求,也增强了公司的竞争力。

AD Semiconductor公司的发展小趣事

ALCOA,全称美国铝业公司,其发展历程可追溯至19世纪末。当时,铝在地球上蕴藏丰富,但提炼单质的铝却十分困难。年轻的查尔斯·霍尔(Charles Hall)发明了用电解方式生产单质铝的方法,并于1889年获得专利。随后,他与艾尔弗雷德·亨特(Alfred E. Hunt)船长合作,投资建厂,开始批量生产铝。这一技术创新不仅推动了铝产量的快速上升,还使得铝这种曾经比金子还贵的金属逐渐走进了人们的日常生活。

问答坊 | AI 解惑

什么是移动通信网络优化(扫盲篇)

什么是移动通信网络优化(扫盲篇) 西安巨人培训中心  党军虎   注:转载请注明出处“西安巨人培训中心”,不得修改原文,否则追究相关责任! 前言 当前咨询或参加我们培训的学员多次要求:希望能够给大家介绍什么是移动 ...…

查看全部问答>

WinCE 5.0 能否在vista下开发?

如题。 我是安装了,sysgen时会死掉,问题说是好像PBCE.EXE执行有冲突。 有没有解决办法呢?急!…

查看全部问答>

如何自绘CDateTimeCtrl中spin控件?

wince里scroll bar的箭头用的是图片,spin控件的箭头好象是用poly line的方式画出来的 结果替换了scroll bar的箭头图片后两种箭头就不一至了,不好看 各位大侠有没有碰过这类问题? …

查看全部问答>

FPGA配置芯片epc2L20工作电压

如题  找了好久没找到...…

查看全部问答>

求问 WINCE中如何判断平台是否有触发呢? 谢谢

要开发一个应用,wince平台的机子,在机子没有被触摸或者点击的情况下在特定的时间里关闭。 wince平台如果被点击或者触摸(触摸屏)或者有程序在运行就会有 发送一个消息,如何判断是否有消息呢? 谢谢 还有 wince驱动中有自带的计时器么? …

查看全部问答>

HPC如何使用toolhelp.lib的函数?

我用的是WinCE5.0 编译错误: error LNK2019: unresolved external symbol _Process32Next referenced in function ... 在用到Process32Next()等的文件里加了下面两行还是没用。 #include #pragma comment (lib,\"toolhelp.lib\") 在task ...…

查看全部问答>

在编译U-BOOT的时候出现错误

在编译U-BOOT的时候出现 以下错误是什么原因啊 make[1]: *** [.depend] 错误 1 make[1]: Leaving directory `/root/Desktop nux/u-boot-1.1.6/cpu/arm920t\' make: *** [cpu/arm920t/start.o] 错误 2 有谁作过的 谢谢指教了 我用的扳子是2410 ...…

查看全部问答>

从USB接口捕获数据的问题

先描述一下问题吧:     现在有一个USB设备,有驱动盘的。需要做一个客户端程序来捕获该设备通过USB传送过来的数据。也就是完成驱动和客户软件的通信,但是现在无法看到驱动程序的内部,有没有什么好的办法?     希望可以 ...…

查看全部问答>

怎么判断按键已经弹起

就是我想用一个按钮控制51单片机的一个中断(低电平触法),中断执行完后就根据中断程序去执行其他的程序。但是在这里遇到一个问题:就是我的中断程序很短(几微秒就执行完),我按下按钮的时候瞬间就执行完了。但是由于此时我的按钮还是处于按下状 ...…

查看全部问答>