电视频道记忆功能,交通灯倒计时时间的设定,户外 led 广告的记忆功能,都有可能用到 eeprom 这类存储器件。这类器件的优势是存储的数据不仅可以改变,而且掉电后数据保存不丢失,因此大量应用在各种电子产品上。
我们这节课的例程,有点类似广告屏。上电后,1602 的第一行显示 eeprom 从 0x20 地址开始的 16 个字符,第二行显示 eerpom 从 0x40 开始的 16 个字符。我们可以通过 uart串口通信来改变 eeprom 内部的这个数据,并且同时也改变了 1602 显示的内容,下次上电的时候,直接会显示我们更新过的内容。
这个程序所有的相关内容,前面都已经讲过了。但是这个程序体现在了一个综合应用能力上。这个程序用到了 1602 液晶、uart 串口通信、eeprom 读写操作等多个功能的综合应用。写个点亮小灯好简单,但是我们想真正学好单片机,必须得学会这种综合程序的应用,实现多个模块同时参与工作。因此同学们,要认认真真的把工程建立起来,一行一行的把程序编写起来,最终巩固下来。
#include
unsigned char t0rh = 0; //t0 重载值的高字节
unsigned char t0rl = 0; //t0 重载值的低字节
void initshowstr();
void configtimer0(unsigned int ms);
extern void initlcd1602();
extern void lcdshowstr(unsigned char x, unsigned char y, unsigned char *str);
extern void e2read(unsigned char *buf, unsigned char addr, unsigned char len);
extern void e2write(unsigned char *buf, unsigned char addr, unsigned char len);
extern void uartdriver();
extern void configuart(unsigned int baud);
extern void uartrxmonitor(unsigned char ms);
extern void uartwrite(unsigned char *buf, unsigned char len);
void main(){
ea = 1; //开总中断
configtimer0(1); //配置 t0 定时 1ms
configuart(9600); //配置波特率为 9600
initlcd1602(); //初始化液晶
initshowstr(); //初始显示内容
while (1){
uartdriver(); //调用串口驱动
}
}
/* 处理液晶屏初始显示内容 */
void initshowstr(){
unsigned char str[17];
str[16] = ‘’;//在最后添加字符串结束符,确保字符串可以结束
e2read(str, 0x20, 16); //读取第一行字符串,其 e2 起始地址为 0x20
lcdshowstr(0, 0, str); //显示到液晶屏
e2read(str, 0x40, 16); //读取第二行字符串,其 e2 起始地址为 0x40
lcdshowstr(0, 1, str); //显示到液晶屏
}
/* 内存比较函数,比较两个指针所指向的内存数据是否相同,
ptr1-待比较指针 1,ptr2-待比较指针 2,len-待比较长度
返回值-两段内存数据完全相同时返回 1,不同返回 0 */
bit cmpmemory(unsigned char *ptr1, unsigned char *ptr2, unsigned char len){
while (len--){
if (*ptr1++ != *ptr2++){ //遇到不相等数据时即刻返回 0
return 0;
}
}
return 1; //比较完全部长度数据都相等则返回 1
}
/* 将一字符串整理成 16 字节的固定长度字符串,不足部分补空格
out-整理后的字符串输出指针,in-待整理字符串指针 */
void trimstring16(unsigned char *out, unsigned char *in){
unsigned char i = 0;
while (*in != ‘’){ //拷贝字符串直到输入字符串结束
*out++ = *in++;
i++;
if (i 》= 16){ //当拷贝长度已达到 16 字节时,强制跳出循环
break;
}
}
for ( ; i《16; i++){ //如不足 16 个字节则用空格补齐
*out++ = ‘ ’;
}
*out = ‘’; //最后添加结束符
}
/* 串口动作函数,根据接收到的命令帧执行响应的动作
buf-接收到的命令帧指针,len-命令帧长度 */
void uartaction(unsigned char *buf, unsigned char len){
unsigned char i;
unsigned char str[17];
unsigned char code cmd0[] = “showstr1 ”; //第一行字符显示命令
unsigned char code cmd1[] = “showstr2 ”; //第二行字符显示命令
unsigned char code cmdlen[] = { //命令长度汇总表
sizeof(cmd0)-1, sizeof(cmd1)-1,
};
unsigned char code *cmdptr[] = { //命令指针汇总表
&cmd0[0], &cmd1[0],
};
for (i=0; i
if (len 》= cmdlen[i]){ //首先接收到的数据长度要不小于命令长度
if (cmpmemory(buf, cmdptr[i], cmdlen[i])){ //比较相同时退出循环
break;
}
}
}
switch (i){ //根据比较结果执行相应命令
case 0:
buf[len] = ‘’; //为接收到的字符串添加结束符
trimstring16(str, buf+cmdlen[0]); //整理成 16 字节固定长度字符串
lcdshowstr(0, 0, str); //显示字符串 1
e2write(str, 0x20, sizeof(str)); //保存字符串 1,起始地址为 0x20
break;
case 1:
buf[len] = ‘’; //为接收到的字符串添加结束符
trimstring16(str, buf+cmdlen[1]); //整理成 16 字节固定长度字符串
lcdshowstr(0, 1, str); //显示字符串 1
e2write(str, 0x40, sizeof(str)); //保存字符串 2,起始地址为 0x40
break;
default: //未找到相符命令时,给上机发送“错误命令”的提示
uartwrite(“bad command.rn”, sizeof(“bad command.rn”)-1);
return;
}
buf[len++] = ‘r’; //有效命令被执行后,在原命令帧之后添加
buf[len++] = ‘n’; //回车换行符后返回给上位机,表示已执行
uartwrite(buf, len);
}
/* 配置并启动 t0,ms-t0 定时时间 */
void configtimer0(unsigned int ms){
unsigned long tmp; //临时变量
tmp = 11059200 / 12; //定时器计数频率
tmp = (tmp * ms) / 1000; //计算所需的计数值
tmp = 65536 - tmp; //计算定时器重载值
tmp = tmp + 33; //补偿中断响应延时造成的误差
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 中断服务函数,执行串口接收监控和蜂鸣器驱动 */
void interrupttimer0() interrupt 1{
th0 = t0rh; //重新加载重载值
tl0 = t0rl;
uartrxmonitor(1); //串口接收监控
}
我们在学习 uart 通信的时候,刚开始也是用的io口去模拟uart通信过程,最终实现和电脑的通信,而后因为 stc89c52 内部具备 uart 硬件通信模块,所以我们直接可以通过配置寄存器就可以很轻松的实现单片机的 uart 通信。同样的道理,这个 i2c 通信,如果单片机内部有硬件模块的话,单片机可以直接自动实现 i2c 通信了,就不需要我们再进行 io口模拟起始、模拟发送、模拟结束,配置好寄存器,单片机就会把这些工作全部做了。
不过我们的stc89c52单片机内部不具备i2c的硬件模块,所以我们使用stc89c52进行i2c通信的话必须用io口来模拟。使用io口模拟i2c实际上更有利于我们彻底理解透彻i2c通信的实质。当然了,通过学习io口模拟通信,今后如果遇到内部带 i2c 模块的单片机,也应该很轻松的搞定,使用内部的硬件模块,可以提高程序的执行效率。
来源;21ic
OLED显示屏为何会失效?实物和参数对比,看完这篇文章就懂了
电路设计小Tips:低功率铂电阻温度检测器 (RTD)传感器电路,在采用一个2.6V电源轨供电时仅吸收35μA总电源电流
莱特波特:测试不革新,智能手机/平板电脑将受产能所限
典型高亮度LED生产环节全方位测试方案
受中美贸易争端,iPhone中国市场需求大降50%?
STC89C52单片机和EEPROM存储器的编程设计
天马推出业界首个3D深度融合VR显示解决方案
在5G、芯片等赛道中,聪明公司已开始引领下一轮增长
意法推出智能型开关按键控制器芯片STM6600/STM660
“融合时代”即将来临?手机内置氮化镓有哪些优势
TN接地系统_TN系统的区别_TN系统用在什么场合
工程监测无线中继采集仪的参数读写MODBUS协议
移动WiMAX技术的特点与应用
程序员加班的意义
友道智途获全国首批无人驾驶路测牌照
为什么要进行高质量发展
取消流量“漫游”费现在的落地情况如何,哪些人将最受益?
三大场景,这款伺服控制器这样点亮生活
配电室环境监测系统解决方案
数据科学家与机器学习工程师怎么区分