第二十一集 Flash模拟EEPROM 课后小练
虽然看上去只有几句要求,但做起来还是有点麻烦。按键又增加了一个,单独用矩阵键盘是不够用了。要用到ADC键盘,我把这两个键盘都用上了,可以同时工作,类似于笔记本电脑的大小键盘 。
下载程序的时候需要注意一点:不选择“下次下载用户程序时擦除用户EEPROM区”,不然保存在EEPROM 的数据,经过一次下载就没了,还不知道问题出在哪里。当然,如你需要,可以选择擦除。
- void main(void)
- {
- Sys_init(); //系统初始化
- usb_init(); //USB CDC 接口配置
-
- IE2 |= 0x80; //使能USB中断
- Timer0_Init(); //定时器初始化
- ADC_Init();
- EA = 1; //IE |= 0X80;
- WDT_CONTR = 0x25; //使能看门狗,溢出时间约1.05S
- //while (DeviceState != DEVSTATE_CONFIGURED); //等待USB完成配置
- //P40 = 0 ;
- Parm_Init();
-
- while(1)
- {
-
- if( blink_stop) //新密码输入完成,再次按下“#”键,这里是ADC键盘F号键
- if(ADC_KEY_READ(ADC_Read(0))==15)
- {
- admin = 0 ;blink_stop = 0;
- EEPROM_SectorErase(E_ADDR); //清空地址里的数据,擦除扇区
- memcpy(dat,cod,8);
- dat[8] = SYS_Run_times;
- dat[9] = (u8)(dat[0]+dat[1]+dat[2]+dat[3]+dat[4]+dat[5]+dat[6]+dat[7]+dat[8]);
- EEPROM_write_n(E_ADDR,dat,10);
-
- }
-
- Task_Pro_Handler_Callback(); //执行功能函数
- WDT_CONTR = 0x35; //清看门狗
- }
- }
复制代码
- u8 SYS_Run_times = 0;
- u8 dat[10]; //0-7:8位密码 8:开机次数 9:校验码(累加校验)
- /*任务1:实现手册的EEPROM的基本操作,并用数码管显示当前的数值。并实现每次重新开机数值+1*/
- void Parm_Init(void)
- {
- EEPROM_read_n( E_ADDR ,dat,10 );
- if( dat[8] == 0xff ) //如果读取到的数据是0xff,就是第一次上电,此时可以初始化
- {
- EEPROM_SectorErase(E_ADDR); //清空地址里的数据,擦除扇区
- memcpy(dat,cod2,8);
- dat[8] = 1;
- dat[9] = (u8)(dat[0]+dat[1]+dat[2]+dat[3]+dat[4]+dat[5]+dat[6]+dat[7]+dat[8]);
- EEPROM_write_n(E_ADDR,dat,10);
-
- //SYS_Run_times = 1;
- }
- else //第二次及其之后的上电
- {
- if( dat[9] == (u8)(dat[0]+dat[1]+dat[2]+dat[3]+dat[4]+dat[5]+dat[6]+dat[7]+dat[8]) ) //校验通过,数据有效
- {
- SYS_Run_times = dat[8];
- SYS_Run_times +=1;
- memcpy(cod2,dat,8);
- }
- else
- {
- //如果数据校验出错,执行什么
- }
- }
- }
复制代码
- sbit COL1 = P0^0; //矩阵键盘的数据口端口定义
- sbit COL2 = P0^1;
- sbit COL3 = P0^2;
- sbit COL4 = P0^3;
- sbit ROW1 = P0^6;
- sbit ROW2 = P0^7;
-
- //矩阵端口数据处理
- void Matrixkey_W(u8 m) //向6个管脚写入数据
- {
- COL1 = m & (0x01<<0);
- COL2 = m & (0x01<<1);
- COL3 = m & (0x01<<2);
- COL4 = m & (0x01<<3);
- ROW1 = m & (0x01<<4);
- ROW2 = m & (0x01<<5);
- // ROW3 = m & (0x01<<6);
- // ROW4 = m & (0x01<<7);
- }
- u8 Matrixkey_R() //从6个管脚读出数据
- {
- u8 n =0;
- // n &= (u8)COL1;
- if(COL1)
- n |= 0x01;
- if(COL2)
- n |= 0x02;
- if(COL3)
- n |= 0x04;
- if(COL4)
- n |= 0x08;
- if(ROW1)
- n |= 0x10;
- if(ROW2)
- n |= 0x20;
- // if(ROW3)
- // n |= 0x40;
- // if(ROW4)
- // n |= 0x80;
- return n;
- }
-
- void KEY_Task(void) //2*4矩阵键盘扫描
- {
- u8 key_temp;
- u8 key1,key2;
- Matrixkey_W(0x30);
- key1 = Matrixkey_R();
- if(key1 != 0x30 )
- {
- key1 = Matrixkey_R()&0x30; //确定哪一行的按键按下
- Matrixkey_W(0x0f);
- key2 = Matrixkey_R();
- if(key2 != 0x0f)
- key2 = Matrixkey_R()&0x0f; //确定哪一列的按键按下
- key_temp=key1|key2; //确定按键位置
- }
- else
- key_temp = key_no;
-
- switch(key_temp) //当确定按键按下后,列举所有的按键情况
- {
- case 0x2e: key_value=0;break;
- case 0x2d: key_value=1;break;
- case 0x2b: key_value=2;break;
- case 0x27: key_value=3;break;
- case 0x1e: key_value=4;break;
- case 0x1d: key_value=5;break;
- case 0x1b: key_value=6;break;
- case 0x17: key_value=7;break;
- case 0xff: key_value=255;break;
- }
- }
复制代码
- void PW_write_Task(void)
- {
- u8 key ;
-
- if(ADC_KEY_READ(ADC_Read(0))==15 & open) //开锁后长按“#”号按键,这里设置ADC15号F按键为“#”号按键
- t_count++;
-
-
- if(t_count>300) //长按“#”号按键3秒,进入管理员模式,admin置一
- {
- admin = 1;
- memcpy(cod ,cod0,8); //将数组cod0的值复制给cod
- t_count = 0;
- }
- if(key_value<11) //只要矩阵键盘或者ADC键盘有按键按下,就把键值读入。
- key = key_value; //实现两组按键同时起作用
- else
- key = ADC_KEY_READ(ADC_Read(0));
- if( key< 11 )
- {
- Key_num ++ ;
-
- if(Key_num ==6)
- {
- j++;
- if(open ==0 )
- {
- cod[j-1] = cod1[key]; //把收到的数字逐一存入cod[]中
- if(j==8) //如果按了8个数字
- {
- if(!memcmp(cod,cod2,8)) //比较cod与cod2两数组是否相等,若相等显示“--OPEN--”,不等显示初始值“--------”
- open = 1;
- else
- {
- memcpy(cod,cod0,8); //将初始值cod0复制给cod,回到起始状态
- j = 0;
- }
- }
- }
- if(admin)
- {
- cod[j-1] = cod1[key]; //进入管理员模式,把新的密码数字逐一存入cod[]中
- if(j==8) //如果按了8个数字,停止闪烁,正常显示新的密码
- {
- blink_stop = 1;
- }
- }
- if( key ==10)
- {
- j = 0;
- open =0;
- }
- if((open ==0)&&(j==0))
- memcpy(cod,cod0,8); //将初始值cod0复制给cod,回到起始状态
- }
- }
- else
- Key_num = 0;
- }
复制代码
21.EEPROM.zip
(235.76 KB, 下载次数: 15)
|