单片机设计时钟程序c语言,单片机电子时钟程序设计

共用体除非必要,否则我们不推荐使用,枚举的用法比较简单,在本书 19 章的项目实践中有很好的示例,这节课我们先来练习一下结构体的使用。下边这个程序的功能是一个带日期的电子钟,相当于一个简易万年历了,并且加入了按键调时功能。学有余力的同学看到这里,不妨先不看我们提供的代码,自己写写试试。如果能够独立写一个按键可调的万年历程序,单片机可以说基本入门了。如果自己还不能够独立完成这个程序,那么还是老规矩,先抄并且理解,而后自己独立默写出来,并且要边默写边理解。

本例直接忽略了星期这项内容,通过上、下、左、右、回车、ESC 这 6 个按键可以调整时间。这也是一个具有综合练习性质的实例,虽然在功能实现上没有多少难度,但要进行的操作却比较多而且烦琐,同学们可以从中体会到把繁杂的功能实现分解为一步步函数操作的必要性以及方便灵活性。简单说一下这个程序的几个要点,方便大家阅读理解程序。

把 DS1302 的底层操作封装为一个 DS1302.c 文件,对上层应用提供基本的实时时间的操作接口,这个文件也是我们的又一个功能模块了,我们的积累也越来越多了。

定义一个结构体类型 sTime 用来封装日期时间的各个元素,又用该结构体定义了一个时间缓冲区变量 bufTime 来暂存从 DS1302 读出的时间和设置时间时的设定值。需要注意的是在其它文件中要使用这个结构体变量时,必须首先再声明一次 sTime 类型;

定义一个变量 setIndex 来控制当前是否处于设置时间的状态,以及设置时间的哪一位,该值为 0 就表示正常运行,1~12 分别代表可以修改日期时间的 12 个位;

由于这节课的程序功能要进行时间调整,用到了 1602 液晶的光标功能,添加了设置光标的函数,我们要改变哪一位的数字,就在 1602 对应位置上进行光标闪烁,所以 Lcd1602.c在之前文件的基础上添加了两个控制光标的函数;

时间的显示、增减、设置移位等上层功能函数都放在 main.c 中来实现,当按键需要这些函数时则在按键文件中做外部声明,这样做是为了避免一组功能函数分散在不同的文件内而使程序显得凌乱。

/***************************DS1302.c 文件程序源代码*****************************/

#include

sbit DS1302_CE = P1^7;

sbit DS1302_CK = P3^5;

sbit DS1302_IO = P3^4;

struct sTime { //日期时间结构体定义

unsigned int year; //年

unsigned char mon; //月

unsigned char day; //日

unsigned char hour; //时

unsigned char min; //分

unsigned char sec; //秒

unsigned char week; //星期

};

/* 发送一个字节到 DS1302 通信总线上 */

void DS1302ByteWrite(unsigned char dat){

unsigned char mask;

for (mask=0x01; mask!=0; mask<<=1){ //低位在前,逐位移出

if ((mask&dat) != 0){ //首先输出该位数据

DS1302_IO = 1;

}else{

DS1302_IO = 0;

}

DS1302_CK = 1; //然后拉高时钟

DS1302_CK = 0; //再拉低时钟,完成一个位的操作

}

DS1302_IO = 1; //最后确保释放 IO 引脚

}

/* 由 DS1302 通信总线上读取一个字节 */

unsigned char DS1302ByteRead(){

unsigned char mask;

unsigned char dat = 0;

for (mask=0x01; mask!=0; mask<<=1){ //低位在前,逐位读取

if (DS1302_IO != 0){ //首先读取此时的 IO 引脚,并设置 dat 中的对应位

dat |= mask;

}

DS1302_CK = 1; //然后拉高时钟

DS1302_CK = 0; //再拉低时钟,完成一个位的操作

}

return dat; //最后返回读到的字节数据

}

/* 用单次写操作向某一寄存器写入一个字节,reg-寄存器地址,dat-待写入字节 */

void DS1302SingleWrite(unsigned char reg, unsigned char dat){

DS1302_CE = 1; //使能片选信号

DS1302ByteWrite((reg<<1)|0x80); //发送写寄存器指令

DS1302ByteWrite(dat); //写入字节数据

DS1302_CE = 0; //除能片选信号

}

/* 用单次读操作从某一寄存器读取一个字节,reg-寄存器地址,返回值-读到的字节 */

unsigned char DS1302SingleRead(unsigned char reg){

unsigned char dat;

DS1302_CE = 1; //使能片选信号

DS1302ByteWrite((reg<<1)|0x81); //发送读寄存器指令

dat = DS1302ByteRead(); //读取字节数据

DS1302_CE = 0; //除能片选信号

return dat;

}

/* 用突发模式连续写入 8 个寄存器数据,dat-待写入数据指针 */

void DS1302BurstWrite(unsigned char *dat){

unsigned char i;

DS1302_CE = 1;

DS1302ByteWrite(0xBE); //发送突发写寄存器指令

for (i=0; i<8; i++){ //连续写入 8 字节数据

DS1302ByteWrite(dat[i]);

}

DS1302_CE = 0;

}

/* 用突发模式连续读取 8 个寄存器的数据,dat-读取数据的接收指针 */

void DS1302BurstRead(unsigned char *dat){

unsigned char i;

DS1302_CE = 1;

DS1302ByteWrite(0xBF); //发送突发读寄存器指令

for (i=0; i<8; i++){ //连续读取 8 个字节

dat[i] = DS1302ByteRead();

}

DS1302_CE = 0;

}

/* 获取实时时间,即读取 DS1302 当前时间并转换为时间结构体格式 */

void GetRealTime(struct sTime *time){

unsigned char buf[8];

DS1302BurstRead(buf);

time->year = buf[6] + 0x2000;

time->mon = buf[4];

time->day = buf[3];

time->hour = buf[2];

time->min = buf[1];

time->sec = buf[0];

time->week = buf[5];

}

/* 设定实时时间,时间结构体格式的设定时间转换为数组并写入 DS1302 */

void SetRealTime(struct sTime *time){

unsigned char buf[8];

buf[7] = 0;

buf[6] = time->year;

buf[5] = time->week;

buf[4] = time->mon;

buf[3] = time->day;

buf[2] = time->hour;

buf[1] = time->min;

buf[0] = time->sec;

DS1302BurstWrite(buf);

}

/* DS1302 初始化,如发生掉电则重新设置初始时间 */

void InitDS1302(){

unsigned char dat;

struct sTime code InitTime[] = { //2013 年 10 月 8 日 12:30:00 星期二

0x2013,0x10,0x08, 0x12,0x30,0x00, 0x02

};

DS1302_CE = 0; //初始化 DS1302 通信引脚

DS1302_CK = 0;

dat = DS1302SingleRead(0); //读取秒寄存器

if ((dat & 0x80) != 0){ //由秒寄存器最高位 CH 的值判断 DS1302 是否已停止

DS1302SingleWrite(7, 0x00); //撤销写保护以允许写入数据

SetRealTime(&InitTime); //设置 DS1302 为默认的初始时间

}

}

DS1302.c 最终向外提供出与具体时钟芯片寄存器位置无关的、由时间结构类型 sTime 作为接口的实时时间的读取和设置函数,如此处理体现了我们前面提到过的层次化编程的思想。应用层可以不关心底层实现细节,底层实现的改变也不会对应用层造成影响,比如说日后你可能需要换一款时钟芯片,而它与 DS1302 的操作和时间寄存器顺序是不同的,那么你需要做的也仅是针对这款新的时钟芯片设计出底层操作函数,最终提供出同样的以 sTime 为接口的操作函数即可,应用层无需做任何的改动。

/***************************Lcd1602.c 文件程序源代码*****************************/

#include

#define LCD1602_DB P0

sbit LCD1602_RS = P1^0;

sbit LCD1602_RW = P1^1;

sbit LCD1602_E = P1^5;

/* 等待液晶准备好 */

void LcdWaitReady(){

unsigned char sta;

LCD1602_DB = 0xFF;

LCD1602_RS = 0;

LCD1602_RW = 1;

do {

LCD1602_E = 1;

sta = LCD1602_DB; //读取状态字

LCD1602_E = 0;

} while (sta & 0x80); //bit7 等于 1 表示液晶正忙,重复检测直到其等于 0 为止

}

/* 向 LCD1602 液晶写入一字节命令,cmd-待写入命令值 */

void LcdWriteCmd(unsigned char cmd){

LcdWaitReady();

LCD1602_RS = 0;

LCD1602_RW = 0;

LCD1602_DB = cmd;

LCD1602_E = 1;

LCD1602_E = 0;

}

/* 向 LCD1602 液晶写入一字节数据,dat-待写入数据值 */

void LcdWriteDat(unsigned char dat){

LcdWaitReady();

LCD1602_RS = 1;

LCD1602_RW = 0;

LCD1602_DB = dat;

LCD1602_E = 1;

LCD1602_E = 0;

}

/* 设置显示 RAM 起始地址,亦即光标位置,(x,y)-对应屏幕上的字符坐标 */

void LcdSetCursor(unsigned char x, unsigned char y){

unsigned char addr;

if (y == 0){ //由输入的屏幕坐标计算显示 RAM 的地址

addr = 0x00 + x; //第一行字符地址从 0x00 起始

}else{

addr = 0x40 + x; //第二行字符地址从 0x40 起始

}

LcdWriteCmd(addr | 0x80); //设置 RAM 地址

}

/* 在液晶上显示字符串,(x,y)-对应屏幕上的起始坐标,str-字符串指针 */

void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str){

LcdSetCursor(x, y); //设置起始地址

while (*str != '\0'){ //连续写入字符串数据,直到检测到结束符

LcdWriteDat(*str++);

}

}

/* 打开光标的闪烁效果 */

void LcdOpenCursor(){

LcdWriteCmd(0x0F);

}

/* 关闭光标显示 */

void LcdCloseCursor(){

LcdWriteCmd(0x0C);

}

/* 初始化 1602 液晶 */

void InitLcd1602(){

LcdWriteCmd(0x38); //16*2 显示,5*7 点阵,8 位数据接口

LcdWriteCmd(0x0C); //显示器开,光标关闭

LcdWriteCmd(0x06); //文字不动,地址自动+1

LcdWriteCmd(0x01); //清屏

}

为了本例的具体需求,在之前文件的基础上添加两个控制光标效果打开和关闭的函数,虽然函数都很简单,但为了保持程序整体上良好的模块化和层次化,还是应该在液晶驱动文件内以函数的形式提供,而不是由应用层代码直接来调用具体的液晶写命令操作。

/***************************keyboard.c 文件程序源代码****************************/

(此处省略,可参考之前章节的代码)

/*****************************main.c 文件程序源代码******************************/

#include

struct sTime { //日期时间结构体定义

unsigned int year;

unsigned char mon;

unsigned char day;

unsigned char hour;

unsigned char min;

unsigned char sec;

unsigned char week;

};

bit flag200ms = 1; //200ms 定时标志

struct sTime bufTime; //日期时间缓冲区

unsigned char setIndex = 0; //时间设置索引

unsigned char T0RH = 0; //T0 重载值的高字节

unsigned char T0RL = 0; //T0 重载值的低字节

void ConfigTimer0(unsigned int ms);

void RefreshTimeShow();

extern void InitDS1302();

extern void GetRealTime(struct sTime *time);

extern void SetRealTime(struct sTime *time);

extern void KeyScan();

extern void KeyDriver();

extern void InitLcd1602();

extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);

extern void LcdSetCursor(unsigned char x, unsigned char y);

extern void LcdOpenCursor();

extern void LcdCloseCursor();

void main(){

unsigned char psec=0xAA; //秒备份,初值 AA 确保首次读取时间后会刷新显示

EA = 1; //开总中断

ConfigTimer0(1); //T0 定时 1ms

InitDS1302(); //初始化实时时钟

InitLcd1602(); //初始化液晶

//初始化屏幕上固定不变的内容

LcdShowStr(3, 0, "20 - - ");

LcdShowStr(4, 1, " : : ");

while (1){

KeyDriver(); //调用按键驱动

if (flag200ms && (setIndex == 0)){ //每隔 200ms 且未处于设置状态时,

flag200ms = 0;

GetRealTime(&bufTime); //获取当前时间

if (psec != bufTime.sec){ //检测到时间有变化时刷新显示

RefreshTimeShow();

psec = bufTime.sec; //用当前值更新上次秒数

}

}

}

}

/* 将一个 BCD 码字节显示到屏幕上,(x,y)-屏幕起始坐标,bcd-待显示 BCD 码 */

void ShowBcdByte(unsigned char x, unsigned char y, unsigned char bcd){

unsigned char str[4];

str[0] = (bcd >> 4) + '0';

str[1] = (bcd&0x0F) + '0';

str[2] = '\0';

LcdShowStr(x, y, str);

}

/* 刷新日期时间的显示 */

void RefreshTimeShow(){

ShowBcdByte(5, 0, bufTime.year);

ShowBcdByte(8, 0, bufTime.mon);

ShowBcdByte(11, 0, bufTime.day);

ShowBcdByte(4, 1, bufTime.hour);

ShowBcdByte(7, 1, bufTime.min);

ShowBcdByte(10, 1, bufTime.sec);

}

/* 刷新当前设置位的光标指示 */

void RefreshSetShow(){

switch (setIndex){

case 1: LcdSetCursor(5, 0); break;

case 2: LcdSetCursor(6, 0); break;

case 3: LcdSetCursor(8, 0); break;

case 4: LcdSetCursor(9, 0); break;

case 5: LcdSetCursor(11, 0); break;

case 6: LcdSetCursor(12, 0); break;

case 7: LcdSetCursor(4, 1); break;

case 8: LcdSetCursor(5, 1); break;

case 9: LcdSetCursor(7, 1); break;

case 10: LcdSetCursor(8, 1); break;

case 11: LcdSetCursor(10, 1); break;

case 12: LcdSetCursor(11, 1); break;

default: break;

}

}

/* 递增一个 BCD 码的高位 */

unsigned char IncBcdHigh(unsigned char bcd){

if ((bcd&0xF0) < 0x90){

bcd += 0x10;

}else{

bcd &= 0x0F;

}

return bcd;

}

/* 递增一个 BCD 码的低位 */

unsigned char IncBcdLow(unsigned char bcd){

if ((bcd&0x0F) < 0x09){

bcd += 0x01;

}else{

bcd &= 0xF0;

}

return bcd;

}

/* 递减一个 BCD 码的高位 */

unsigned char DecBcdHigh(unsigned char bcd){

if ((bcd&0xF0) > 0x00){

bcd -= 0x10;

}else{

bcd |= 0x90;

}

return bcd;

}

/* 递减一个 BCD 码的低位 */

unsigned char DecBcdLow(unsigned char bcd){

if ((bcd&0x0F) > 0x00){

bcd -= 0x01;

}else{

bcd |= 0x09;

}

return bcd;

}

/* 递增时间当前设置位的值 */

void IncSetTime(){

switch (setIndex){

case 1: bufTime.year = IncBcdHigh(bufTime.year); break;

case 2: bufTime.year = IncBcdLow(bufTime.year); break;

case 3: bufTime.mon = IncBcdHigh(bufTime.mon); break;

case 4: bufTime.mon = IncBcdLow(bufTime.mon); break;

case 5: bufTime.day = IncBcdHigh(bufTime.day); break;

case 6: bufTime.day = IncBcdLow(bufTime.day); break;

case 7: bufTime.hour = IncBcdHigh(bufTime.hour); break;

case 8: bufTime.hour = IncBcdLow(bufTime.hour); break;

case 9: bufTime.min = IncBcdHigh(bufTime.min); break;

case 10: bufTime.min = IncBcdLow(bufTime.min); break;

case 11: bufTime.sec = IncBcdHigh(bufTime.sec); break;

case 12: bufTime.sec = IncBcdLow(bufTime.sec); break;

default: break;

}

RefreshTimeShow();

RefreshSetShow();

}

/* 递减时间当前设置位的值 */

void DecSetTime(){

switch (setIndex){

case 1: bufTime.year = DecBcdHigh(bufTime.year); break;

case 2: bufTime.year = DecBcdLow(bufTime.year); break;

case 3: bufTime.mon = DecBcdHigh(bufTime.mon); break;

case 4: bufTime.mon = DecBcdLow(bufTime.mon); break;

case 5: bufTime.day = DecBcdHigh(bufTime.day); break;

case 6: bufTime.day = DecBcdLow(bufTime.day); break;

case 7: bufTime.hour = DecBcdHigh(bufTime.hour); break;

case 8: bufTime.hour = DecBcdLow(bufTime.hour); break;

case 9: bufTime.min = DecBcdHigh(bufTime.min); break;

case 10: bufTime.min = DecBcdLow(bufTime.min); break;

case 11: bufTime.sec = DecBcdHigh(bufTime.sec); break;

case 12: bufTime.sec = DecBcdLow(bufTime.sec);

default: break;

}

RefreshTimeShow();

RefreshSetShow();

}

/* 右移时间设置位 */

void RightShiftTimeSet(){

if (setIndex != 0){

if (setIndex < 12){

setIndex++;

}else{

setIndex = 1;

}

RefreshSetShow();

}

}

/* 左移时间设置位 */

void LeftShiftTimeSet(){

if (setIndex != 0){

if (setIndex > 1){

setIndex--;

}else{

setIndex = 12;

}

RefreshSetShow();

}

}

/* 进入时间设置状态 */

void EnterTimeSet(){

setIndex = 2; //把设置索引设置为 2,即可进入设置状态

LeftShiftTimeSet(); //再利用现成的左移操作移到位置 1 并完成显示刷新

LcdOpenCursor(); //打开光标闪烁效果

}

/* 退出时间设置状态,save-是否保存当前设置的时间值 */

void ExitTimeSet(bit save){

setIndex = 0; //把设置索引设置为 0,即可退出设置状态

if (save){ //需保存时即把当前设置时间写入 DS1302

SetRealTime(&bufTime);

}

LcdCloseCursor(); //关闭光标显示

}

/* 按键动作函数,根据键码执行相应的操作,keycode-按键键码 */

void KeyAction(unsigned char keycode){

if ((keycode>='0') && (keycode<='9')){ //本例中不响应字符键

}else if (keycode == 0x26){ //向上键,递增当前设置位的值

IncSetTime();

}else if (keycode == 0x28){ //向下键,递减当前设置位的值

DecSetTime();

}else if (keycode == 0x25){ //向左键,向左切换设置位

LeftShiftTimeSet();

}else if (keycode == 0x27){ //向右键,向右切换设置位

RightShiftTimeSet();

}else if (keycode == 0x0D){ //回车键,进入设置模式/启用当前设置值

if (setIndex == 0){ //不处于设置状态时,进入设置状态

EnterTimeSet();

}else{ //已处于设置状态时,保存时间并退出设置状态

ExitTimeSet(1);

}

}else if (keycode == 0x1B){ //Esc 键,取消当前设置

ExitTimeSet(0);

}

}

/* 配置并启动 T0,ms-T0 定时时间 */

void ConfigTimer0(unsigned int ms){

unsigned long tmp; //临时变量

tmp = 11059200 / 12; //定时器计数频率

tmp = (tmp * ms) / 1000; //计算所需的计数值

tmp = 65536 - tmp; //计算定时器重载值

tmp = tmp + 28; //补偿中断响应延时造成的误差

T0RH = (unsigned char)(tmp>>8); //定时器重载值拆分为高低字节

T0RL = (unsigned char)tmp;

TMOD &= 0xF0; //清零 T0 的控制位

TMOD |= 0x01; //配置 T0 为模式 1

TH0 = T0RH; //加载 T0 重载值

TL0 = T0RL;

ET0 = 1; //使能 T0 中断

TR0 = 1; //启动 T0

}

/* T0 中断服务函数,执行按键扫描和 200ms 定时 */

void InterruptTimer0() interrupt 1{

static unsigned char tmr200ms = 0;

TH0 = T0RH; //重新加载重载值

TL0 = T0RL;

KeyScan(); //按键扫描

tmr200ms++;

if (tmr200ms >= 200){ //定时 200ms

tmr200ms = 0;

flag200ms = 1;

}

}

main.c 主文件,负责所有应用层的功能实现,文件比较长,还是那句话“不难但比较烦琐”,希望对具体问题分析细化能力还不太强的同学们把这个文件多练习几遍,学习一下其中把具体问题逐步细化并一步步实现出来的编程思想,多进行此类练习,锻炼程序思维能力,将来遇到具体项目设计需求的时候,你很快就可以找到方法并实现它们了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/335306.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

本地 Windows 如何将 Web 工程部署到远程 Windows 主机上

文章目录第一步&#xff1a;先连接远程 Windows 主机&#xff1a;第二步&#xff1a;连接远程 Windows 主机后&#xff0c;把发布包复制到远程主机上并确定有关的目录第三步&#xff1a;删除远程主机的数据库中的旧数据第四步&#xff1a;创建新的用户和表空间第五步&#xff1…

kafka streams_Kafka REST Proxy MapR Streams入门

kafka streamsMapR生态系统软件包2.0&#xff08;MEP&#xff09;随附了一些与MapR流有关的新功能&#xff1a; 用于MapR Streams的Kafka REST代理为MapR Streams和Kafka集群提供了RESTful接口&#xff0c;使其易于使用和产生消息以及执行管理操作。 Kafka Connect for MapR …

r语言三维柱状图_R语言三维图的绘制

R语言在可视化方面的地位是毋庸置疑的&#xff0c;但是呢相对于MatalabR语言在三维图形的展示上存在一定的劣势。当然&#xff0c;作为大众的免费软件&#xff0c;指定不服&#xff0c;很多人为此也基于R语言开发了一些相应的三维图的绘制包&#xff0c;像rgl&#xff0c;gg3D&…

从事仪表专业学c语言有用吗,测控专业就业方向有哪些 就业前景比你想象中的好...

测控专业就业方向有哪些?这个专业的就业前景好不好?这些问题都是小伙伴们比较关心的问题&#xff0c;下面随小编一起来了解一下吧。主要就业方向1.智能仪器仪表方向&#xff0c;我觉得这个方向主要是从事仪器仪表&#xff0c;电子产品的软件&#xff0c;硬件研发&#xff0c;…

c语言 将url图片存到本地_python爬虫:爬取男生喜欢的图片

任务目标&#xff1a;1.抓取不同类型的图片2.编写一个GUI界面爬虫程序&#xff0c;打包成exe重新文件3.遇到的难点1.分析如何抓取不同类型的图片首先打开网站&#xff0c;可以看到有如下6个类型的菜单在这里插入图片描述点击不同菜单&#xff0c;发现URL显示如下大胸妹&#xf…

hazelcast集群配置_使用HazelCast进行Hibernate缓存:基本配置

hazelcast集群配置之前&#xff0c;我们对JPA缓存&#xff0c;机制以及hibernate提供的内容进行了介绍 。 接下来是一个使用Hazelcast作为二级缓存的Hibernate项目。 为此&#xff0c;我们将在JPA中使用一个基本的spring boot项目。 Spring Boot使用Hibernate作为默认的JPA提…

c语言编译后找不到exe,在VS 2015命令提示符中找不到c – rc.exe

我刚刚安装了Windows 10 Creators Update(版本10.0.15063).我安装了多个版本的Visual Studio(2012年,2013年,2015年和2017年).我几周前才安装了VS 2017.问题在“VS2015 x64本机命令提示符”中运行时,CMake(版本3.8.1)不再找到C/C编译器(在VS 2017命令提示符下运行时它可以正常工…

tomcat如何通过配置的方式部署web工程

Workspaces 下有很多工程文件&#xff0c;这个 Workspaces 是 Myeclipse 自动生成的&#xff0c;我们通过 Myeclipse 写的工程都在这个 Workspaces 文件夹下。 我们部署工程到服务器上&#xff0c;就是要每个 WEB 工程里面的 context 文件夹&#xff0c;这个文件夹可以放在 t…

python爬虫源码_Python—爬虫:王者荣耀全套皮肤【附源码】

怎么获取全套皮肤&#xff1f;用钱买&#xff0c;或者用爬虫爬取下来~虽然后者不能穿。这个案例稍微复杂一点&#xff0c;但是一个非常值得学习的项目。具体实现思路&#xff1a;分析网页源代码结构找到合适的入口穷举访问并解析爬取所有英雄所有皮肤图片代码思路/程序流程&…

java ee规范_测试Java EE 8规范

java ee规范Java EE 8平台肯定在过去的几个月中一直在发展。 规范已经发布了早期的草案评审&#xff0c;里程碑甚至最终版本。 实际上&#xff0c;随着JSF 2.3的发布&#xff0c;JSR-372才刚刚进入最终版本。 有关更多信息&#xff0c;请参见 Arjan的帖子 。 它有幸成为JSR-37…

c语言中Gretchen函数的功能,听过很多的歌的音乐达人给我推荐一下

『 挚爱篇 』1 Bloated -- 挚爱篇2 Joy Is WIthin Reach -- Adrienne3 First Love -- 挚爱篇4 First Time -- 挚爱篇5 Get Funky -- 挚爱篇6 Walking on Air -- 挚爱篇7 Por qu te vas -- 挚爱篇8 爵士慢摇曲 -- Milky9 I Just Cant Get You Out of My Head (Club Mix) -- 挚爱…

JavaScript(JS)常用正则表达式汇总

文章目录自定义字符串校验函数常用正则表达式自定义字符串校验函数 校验字符串是否全由数字组成&#xff0c;是则返回true&#xff0c;否则返回false&#xff1a; function isDigit(str) {var regExp /^[0-9]{1,20}$/;// exec方法如果找到符合正则表达式的字符串&#xff0c…

警惕成教自考_不,保持警惕不会伤害Java。 关于Java许可的评论。

警惕成教自考所以。 Oracle希望通过Java赚钱。 然后&#xff0c;The Register发表了一篇非常对立的文章&#xff0c;上面有一个超级吸引人的标题。 根据他们的消息来源&#xff0c;“ Oracle正在大力加强对声称违反其许可证的Java客户的审计”。 当Twitter诗句对人们批评Oracle…

android colorstatelist_Android 样式系统 | 主题背景属性

在 Android 样式系统系列的前几篇文章中&#xff0c;我们介绍了主题背景与样式的区别&#xff0c;以及为什么说通过主题背景和公共主题背景属性来分解您要实现的内容是一个不错的主意&#xff0c;请点击链接回顾:Android 样式系统 | 主题背景和样式Android 样式系统 | 常见的主…

浙江科技学院c语言考试试卷,浙江科技学院c语言C试卷A.doc

浙江科技学院c语言C试卷A浙江科技学院2012 - 2013学年第学期考试试卷A卷信息、经管、 学院 20 年级 理工科专业得分一、判断题(本大题共12小题&#xff0c;每题小1分&#xff0c;共12分)得分二、单选题(本大题共20小题&#xff0c;每题1分&#xff0c;共20分)A.循环控制表达式的…

MyEclipse的Debug功能最基本的操作

使用 Debug 功能最基本的操作&#xff1a; 1.首先在一个 Java 文件中设断点&#xff0c;然后 Debug as --> Open Debug Dialog&#xff0c;然后在对话框中选类后&#xff0c;再点击 Run 运行程序&#xff0c;当程序走到断点处就会自动转到 Debug 视图 2.F5 键与F6 键均为单…

python二级考试可以用pycharm吗_学Python,Pycharm不能不知道怎么用

栏目介绍必会的Pycharm。我决定把去年写的Python文章整理一个专栏&#xff0c;垃圾的就直接删除&#xff0c;将多篇博文整理成一篇。 工欲善其事必先利其器&#xff0c;Pycharm 是最受欢迎的Python开发工具&#xff0c;它提供的功能非常强大&#xff0c;我尽量把自己用的都写写…

C语言写出生命游戏什么水平,我也来汇报~~~生命游戏。

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼int main(void){FILE *wen1,*wen2;system("color f0");char a[1000]{0};int i0;xx ch{0,0};wen1fopen("shuru.txt","r");if (wen1!NULL){while(!feof(wen1)){fread(&a[i],1,1,wen1);}chchinesec…

hazelcast 使用_使用HazelCast进行Hibernate缓存:JPA缓存基础知识

hazelcast 使用HazelCast的最大功能之一就是对Hibernate第二级缓存的支持 。 JPA具有两个级别的缓存。 一级缓存在事务期间缓存对象的状态。 通过两次查询相同的对象&#xff0c;您必须获得第一次获取的对象。 但是&#xff0c;在包含您检索并访问数据库的复杂查询的情况下&…

判断输入的字符串总字节数是否超出限制

function checkByteLength(str) { var bytes 0; for(var i 0;i<str.length;i){ var c str.charAt(i); if(c<256){ bytes 1; }else{ bytes 2; } } if(bytes >6){ alert(“您输入的字数超过限制&#xff01;”); } }