13.2 1602整屏移动

来源:互联网 发布:c语言a =b 编辑:程序博客网 时间:2024/05/16 19:19
我们前边学第 7 章点阵 LED 的时候,可以实现上下移动,左右移动等。而对于 1602 液晶来说,也可以进行屏幕移动,实现我们想要的一些效果,那我们来用一个例程实现字符串在 1602 液晶上的左移。每个人都不要只瞪着眼看,一定要认真抄下来,甚至抄几遍,边抄边理解,要想真正学好,一定要根据我的方法来做。
复制纯文本新窗口
  1. #include <reg52.h>
  2. #define LCD1602_DB P0
  3. sbit LCD1602_RS = P1^0;
  4. sbit LCD1602_RW = P1^1;
  5. sbit LCD1602_E = P1^5;
  6. bit flag500ms = 0; //500ms 定时标志
  7. unsigned char T0RH = 0; //T0 重载值的高字节
  8. unsigned char T0RL = 0; //T0 重载值的低字节
  9. //待显示的第一行字符串
  10. unsigned char code str1[] = "Kingst Studio";
  11. //待显示的第二行字符串,需保持与第一行字符串等长,较短的行可用空格补齐
  12. unsigned char code str2[] = "Let's move...";
  13. void ConfigTimer0(unsigned int ms);
  14. void InitLcd1602();
  15. void LcdShowStr(unsigned char x, unsigned char y,
  16. unsigned char *str, unsigned char len);
  17. void main(){
  18. unsigned char i;
  19. unsigned char index = 0; //移动索引
  20. unsigned char pdata bufMove1[16+sizeof(str1)+16]; //移动显示缓冲区 1
  21. unsigned char pdata bufMove2[16+sizeof(str2)+16]; //移动显示缓冲区 2
  22. EA = 1; //开总中断
  23. ConfigTimer0(10); //配置 T0 定时 10ms
  24. InitLcd1602(); //初始化液晶
  25. //缓冲区开头一段填充为空格
  26. for (i=0; i<16; i++){
  27. bufMove1[i] = ' ';
  28. bufMove2[i] = ' ';
  29. }
  30. //待显示字符串拷贝到缓冲区中间位置
  31. for (i=0; i<(sizeof(str1)-1); i++){
  32. bufMove1[16+i] = str1[i];
  33. bufMove2[16+i] = str2[i];
  34. }
  35. //缓冲区结尾一段也填充为空格
  36. for (i=(16+sizeof(str1)-1); i<sizeof(bufMove1); i++){
  37. bufMove1[i] = ' ';
  38. bufMove2[i] = ' ';
  39. }
  40. while (1){
  41. if (flag500ms){ //每 500ms 移动一次屏幕
  42. flag500ms = 0;
  43. //从缓冲区抽出需显示的一段字符显示到液晶上
  44. LcdShowStr(0, 0, bufMove1+index, 16);
  45. LcdShowStr(0, 1, bufMove2+index, 16);
  46. //移动索引递增,实现左移
  47. index++;
  48. if (index >= (16+sizeof(str1)-1)){
  49. //起始位置达到字符串尾部后即返回从头开始
  50. index = 0;
  51. }
  52. }
  53. }
  54. }
  55. /* 配置并启动 T0,ms-T0 定时时间 */
  56. void ConfigTimer0(unsigned int ms){
  57. unsigned long tmp; //临时变量
  58. tmp = 11059200 / 12; //定时器计数频率
  59. tmp = (tmp * ms) / 1000; //计算所需的计数值
  60. tmp = 65536 - tmp; //计算定时器重载值
  61. tmp = tmp + 12; //补偿中断响应延时造成的误差
  62. T0RH = (unsigned char)(tmp>>8); //定时器重载值拆分为高低字节
  63. T0RL = (unsigned char)tmp;
  64. TMOD &= 0xF0; //清零 T0 的控制位
  65. TMOD |= 0x01; //配置 T0 为模式 1
  66. TH0 = T0RH; //加载 T0 重载值
  67. TL0 = T0RL;
  68. ET0 = 1; //使能 T0 中断
  69. TR0 = 1; //启动 T0
  70. }
  71. /* 等待液晶准备好 */
  72. void LcdWaitReady(){
  73. unsigned char sta;
  74. LCD1602_DB = 0xFF;
  75. LCD1602_RS = 0;
  76. LCD1602_RW = 1;
  77. do{
  78. LCD1602_E = 1;
  79. sta = LCD1602_DB; //读取状态字
  80. LCD1602_E = 0;
  81. //bit7 等于 1 表示液晶正忙,重复检测直到其等于 0 为止
  82. }while (sta & 0x80);
  83. }
  84. /* 向 LCD1602 液晶写入一字节命令,cmd-待写入命令值 */
  85. void LcdWriteCmd(unsigned char cmd){
  86. LcdWaitReady();
  87. LCD1602_RS = 0;
  88. LCD1602_RW = 0;
  89. LCD1602_DB = cmd;
  90. LCD1602_E = 1;
  91. LCD1602_E = 0;
  92. }
  93. /* 向 LCD1602 液晶写入一字节数据,dat-待写入数据值 */
  94. void LcdWriteDat(unsigned char dat){
  95. LcdWaitReady();
  96. LCD1602_RS = 1;
  97. LCD1602_RW = 0;
  98. LCD1602_DB = dat;
  99. LCD1602_E = 1;
  100. LCD1602_E = 0;
  101. }
  102. /* 设置显示 RAM 起始地址,亦即光标位置,(x,y)-对应屏幕上的字符坐标 */
  103. void LcdSetCursor(unsigned char x, unsigned char y){
  104. unsigned char addr;
  105. if (y == 0){ //由输入的屏幕坐标计算显示 RAM 的地址
  106. addr = 0x00 + x; //第一行字符地址从 0x00 起始
  107. }else{
  108. addr = 0x40 + x; //第二行字符地址从 0x40 起始
  109. }
  110. LcdWriteCmd(addr | 0x80); //设置 RAM 地址
  111. }
  112. /* 在液晶上显示字符串,(x,y)-对应屏幕上的起始坐标,
  113. str-字符串指针,len-需显示的字符长度 */
  114. void LcdShowStr(unsigned char x, unsigned char y,
  115. unsigned char *str, unsigned char len){
  116. LcdSetCursor(x, y); //设置起始地址
  117. while (len--){ //连续写入 len 个字符数据
  118. LcdWriteDat(*str++); //先取 str 指向的数据,然后 str 自加 1
  119. }
  120. }
  121. /* 初始化 1602 液晶 */
  122. void InitLcd1602(){
  123. LcdWriteCmd(0x38); //16*2 显示,5*7 点阵,8 位数据接口
  124. LcdWriteCmd(0x0C); //显示器开,光标关闭
  125. LcdWriteCmd(0x06); //文字不动,地址自动+1
  126. LcdWriteCmd(0x01); //清屏
  127. }
  128. /* T0 中断服务函数,定时 500ms */
  129. void InterruptTimer0() interrupt 1{
  130. static unsigned char tmr500ms = 0;
  131. TH0 = T0RH; //重新加载重载值
  132. TL0 = T0RL;
  133. tmr500ms++;
  134. if (tmr500ms >= 50){
  135. tmr500ms = 0;
  136. flag500ms = 1;
  137. }
  138. }
通过这个程序,大家首先要学会 for 语句在数组中的灵活应用,这个其实在数码管显示有效位的例程中已经有所体现了。其次,随着我们后边程序量的增大,大家得学会多个函数之间相互调用的灵活应用,体会其中的奥妙。
0 0
原创粉丝点击