Chinaunix首页 | 论坛 | 博客
  • 博客访问: 160938
  • 博文数量: 35
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 401
  • 用 户 组: 普通用户
  • 注册时间: 2014-11-28 14:09
文章分类

全部博文(35)

文章存档

2015年(27)

2014年(8)

分类: 嵌入式

2015-08-06 15:28:42

整体规划(1课时)

1、用protues进行原理图绘制

2、用keil软件进行代码编写与调试

3Keil + protues进行仿真实验

4、处理器采用Atmel公司的AT89C51,晶振频率12MHz,源代码用C语言编写

5、此项目可以分为3个模块:LCD1602显示部分、按键扫描部分、核心计算部分

LCD1602模块(3课时)

1、阅读LCD1602手册,明白每一个引脚的用途,按照手册连接原理图


2、仔细阅读1602控制指令,编写LCD1602控制程序

指令1:清显示,指令码01H,光标复位到地址00H位置
指令2:光标复位,光标返回到地址00H
指令3:光标和显示模式设置 I/D:光标移动方向,高电平右移,低电平左移 S:屏幕上所有文字是否左移或者右移。高电平表示有效,低电平则无效

指令4:显示开关控制。 D:控制整体显示的开与关,高电平表示开显示,低电平表示关显示 C:控制光标的开与关,高电平表示有光标,低电平表示无光标 B:控制光标是否闪烁,高电平闪烁,低电平不闪烁

指令5:光标或显示移位 S/C:高电平时移动显示的文字,低电平时移动光标

指令6:功能设置命令 DL:高电平时为4位总线,低电平时为8位总线 N:低电平时为单行显示,高电平时双行显示 F: 低电平时显示5x7的点阵字符,高电平时显示5x10的点阵字符

指令7:字符发生器RAM地址设置

指令8DDRAM地址设置

指令9:读忙信号和光标地址 BF:为忙标志位,高电平表示忙,此时模块不能接收命令或者数据,如果为低电平表示不忙。

指令10:写数据

指令11:读数据

点击(此处)折叠或打开

  1. #include <reg52.h>
  2.  
  3. 2. #include <lcd_1602.h>

  4. 3. #define uchar unsigned char

  5. 4.

  6. 5. float power(int num, int p);

  7. 6.int powerr(int num, int p);

  8. 7.

  9. 8.//RS 高电平选择数据 低电平选择命令/地址

  10. 9.//R/W 高电平读 低电平写

  11. 10.

  12. 11.uchar code cmd[] = {

  13. 12. 0x01, //清屏

  14. 13. 0x02, //光标返回00h

  15. 14. 0x06, //开显示,无光标,不闪烁

  16. 15. 0x38 //8位总线,双行显示,5*7阵列

  17. 16. };

  18. 17.

  19. 18.void delay_1ms();

  20. 19. void delay_10us();

  21. 20.

  22. 21.int lcd_1602_busy() //读忙信号

  23. 22.{

  24. 23. uchar tmp;

  25. 24. P0 = 0xff; //将P0口设置为输出

  26. 25. LCD_1602_RW = 1;

  27. 26. LCD_1602_RS = 0;

  28. 27.

  29. 28. LCD_1602_EN = 1;

  30. 29. delay_10us();

  31. 30. tmp = P0;

  32. 31. LCD_1602_EN = 0;

  33. 32.

  34. 33. return (bit)(0x80 & tmp);

  35. 34.

  36. 35.}

  37. 36.

  38. 37. void lcd_1602_write_cmd(uchar cmd) //发送命令\地址

  39. 38.{

  40. 39. while(lcd_1602_busy());

  41. 40.

  42. 41. LCD_1602_RW = 0;

  43. 42. LCD_1602_RS = 0;

  44. 43. P0 = cmd;

  45. 44.

  46. 45. LCD_1602_EN = 1;

  47. 46.// P0 = cmd;

  48. 47. delay_10us();

  49. 48. LCD_1602_EN = 0;

  50. 49.}

  51. 50.

  52. 51. void lcd_1602_write_data(uchar dat) //发送数据

  53. 52.{

  54. 53. while(lcd_1602_busy());

  55. 54.

  56. 55. LCD_1602_RW = 0;

  57. 56. LCD_1602_RS = 1;

  58. 57. P0 = dat;

  59. 58.

  60. 59. LCD_1602_EN = 1;

  61. 60.// P0 = dat;

  62. 61. delay_10us();

  63. 62. LCD_1602_EN = 0;

  64. 63.}

  65. 64.

  66. 65. void lcd_1602_init() //lcd初始化

  67. 66.{

  68. 67. lcd_1602_write_cmd(0x01);

  69. 68. lcd_1602_write_cmd(0x0c);

  70. 69. lcd_1602_write_cmd(0x38);

  71. 70. lcd_1602_write_cmd(0x01);

  72. 71. delay_1ms();

  73. 72.}

  74. 73.

  75. 74. void lcd_1602_write_char(uchar x, uchar y, uchar dat)//写字符

  76. 75.{

  77. 76. if(x == 0)

  78. 77. {

  79. 78. lcd_1602_write_cmd(0x80 + y%16);

  80. 79. lcd_1602_write_data(dat);

  81. 80. }

  82. 81. else

  83. 82. {

  84. 83. lcd_1602_write_cmd(0xc0 + y%16);

  85. 84. lcd_1602_write_data(dat);

  86. 85. }

  87. 86.}

  88. 87.

  89. 88. void lcd_1602_write_string(uchar x, uchar y, uchar *string)//写字符串

  90. 89.{

  91. 90. while(*string != '\0')

  92. 91. {

  93. 92. lcd_1602_write_char(x, y++, *(string++));

  94. 93. }

  95. 94.}

  96. 95.

  97. 96. void lcd_1602_write_num(uchar x, uchar y, float num)//写数字

  98. 97.{

  99. 98. int i;

  100. 99. int nu = (int)num;

  101. 100.

  102. 101. char string[5];

  103. 102. for(i=0; i<4; i++)

  104. 103. {

  105. 104. string[i] = nu/powerr(10, 3-i) + '0';

  106. 105. nu = nu % powerr(10, 3-i);

  107. 106. if(nu < 10)

  108. 107. string[i+1] = nu + '0';

  109. 108. }

  110. 109. string[4] = '\0';

  111. 110. lcd_1602_write_string(x, y, string);

  112. 111.}

  113. 112.

  114. 113.int powerr(int num, int p) //求num的p次方

  115. 114.{

  116. 115. int sum = 1;

  117. 116.

  118. 117. while(p)

  119. 118. {

  120. 119. sum = sum*num;

  121. 120. p--;

  122. 121. }

  123. 122.

  124. 123. return sum;

  125. 124.}
  126.  




  127. 按键模块

  128. 1、阅读课本第10章按键扫描方法

  129. 2、绘制按键原理图

  130. 3、编写按键扫描程序
  131.  




  132. 点击(此处)折叠或打开

  133. 1./**************************************************
  134.  
  135. 2.函数功能:按键扫描

  136. 3. 实现4*4键盘扫描,记录下每一个按键

  137. 4.*****************************************************/

  138. 5.int keyscan()

  139. 6.{

  140. 7.

  141. 8. P3=0xfe;

  142. 9. temp=P3;

  143. 10. temp = temp & 0xf0;

  144. 11. if(temp!=0xf0)

  145. 12. {

  146. 13. delay(10);

  147. 14. if(temp!=0xf0)

  148. 15. {

  149. 16. temp=P3;

  150. 17. switch(temp)

  151. 18. {

  152. 19. case 0xee:

  153. 20. key = '1';

  154. 21. break;

  155. 22.

  156. 23. case 0xde:

  157. 24. key = '2';

  158. 25. break;

  159. 26.

  160. 27. case 0xbe:

  161. 28. key = '3';

  162. 29. break;

  163. 30.

  164. 31. case 0x7e:

  165. 32. key = '+';

  166. 33. break;

  167. 34. }

  168. 35. while(temp!=0xf0)

  169. 36. {

  170. 37. temp=P3;

  171. 38. temp=temp&0xf0;

  172. 39. beep=0;

  173. 40. }

  174. 41. beep=1;

  175. 42. return 1;

  176. 43. }

  177. 44. }

  178. 45. P3=0xfd;

  179. 46. temp=P3;

  180. 47. temp=temp&0xf0;

  181. 48. if(temp!=0xf0)

  182. 49. {

  183. 50. delay(10);

  184. 51. if(temp!=0xf0)

  185. 52. {

  186. 53. temp=P3;

  187. 54. switch(temp)

  188. 55. {

  189. 56. case 0xed:

  190. 57. key='4';

  191. 58. break;

  192. 59.

  193. 60. case 0xdd:

  194. 61. key='5';

  195. 62. break;

  196. 63.

  197. 64. case 0xbd:

  198. 65. key='6';

  199. 66. break;

  200. 67.

  201. 68. case 0x7d:

  202. 69. key='-';

  203. 70. break;

  204. 71. }

  205. 72. while(temp!=0xf0)

  206. 73. {

  207. 74. temp=P3;

  208. 75. temp=temp&0xf0;

  209. 76. beep=0;

  210. 77. }

  211. 78. beep=1;

  212. 79. return 1;

  213. 80. }

  214. 81. }

  215. 82. P3=0xfb;

  216. 83. temp=P3;

  217. 84. temp=temp&0xf0;

  218. 85. if(temp!=0xf0)

  219. 86. {

  220. 87. delay(10);

  221. 88. if(temp!=0xf0)

  222. 89. {

  223. 90. temp=P3;

  224. 91. switch(temp)

  225. 92. {

  226. 93. case 0xeb:

  227. 94. key='7';

  228. 95. break;

  229. 96.

  230. 97. case 0xdb:

  231. 98. key='8';

  232. 99. break;

  233. 100.

  234. 101. case 0xbb:

  235. 102. key='9';

  236. 103. break;

  237. 104.

  238. 105. case 0x7b:

  239. 106. key='*';

  240. 107. break;

  241. 108. }

  242. 109. while(temp!=0xf0)

  243. 110. {

  244. 111. temp=P3;

  245. 112. temp=temp&0xf0;

  246. 113. beep=0;

  247. 114. }

  248. 115. beep=1;

  249. 116. return 1;

  250. 117. }

  251. 118. }

  252. 119. P3=0xf7;

  253. 120. temp=P3;

  254. 121. temp=temp&0xf0;

  255. 122. if(temp!=0xf0)

  256. 123. {

  257. 124. delay(10);

  258. 125. if(temp!=0xf0)

  259. 126. {

  260. 127. temp=P3;

  261. 128. switch(temp)

  262. 129. {

  263. 130. case 0xe7:

  264. 131. key = '0';

  265. 132. lcd_1602_write_data(key);

  266. 133. break;

  267. 134.

  268. 135. case 0xd7:

  269. 136. key='.';

  270. 137. lcd_1602_write_data(key);

  271. 138. break;

  272. 139.

  273. 140. case 0xb7:

  274. 141. key='=';

  275. 142. break;

  276. 143.

  277. 144. case 0x77:

  278. 145. key='/';

  279. 146. break;

  280. 147. }

  281. 148. while(temp!=0xf0)

  282. 149. {

  283. 150. temp=P3;

  284. 151. temp=temp&0xf0;

  285. 152. beep=0;

  286. 153. }

  287. 154. beep=1;

  288. 155. return 1;

  289. 156. }

  290. 157. }

  291. 158. return 0;

  292. 159.}
  293. 核心计算模块

    1、测试LCD1602显示程序是否正确

    2、测试按键扫描程序是否正确

    3、在Linux环境下调试计算程序。

    首先将扫描到的按键存储在数组中,然后从数组提取操作数和操作码,调用计算子程序进行计算,最后输入计算结果。

    以上过程需要先在Linux环境下模拟,因此需要少许Linux知识。

    点击(此处)折叠或打开

    1. #include <reg51.h>
    2.  
    3. 2. #include <stdio.h>

    4. 3. #include <calculate.h>

    5. 4.

    6. 5. extern uchar key;

    7. 6.

    8. 7.int f = 0;

    9. 8.int str_len = 0;

    10. 9.int operand_num = 0;

    11. 10.int operator_num = 0;

    12. 11. float end = 0.0;

    13. 12.int a = 0, b = 0;

    14. 13.

    15. 14. char xdata input[100];

    16. 15. float xdata operand[10]={0};

    17. 16. char xdata operator[10];

    18. 17.

    19. 18. void get_operand(char *string);

    20. 19. void str_int(char *str, float num[]);

    21. 20.

    22. 21. float power(int num, int p);

    23. 22. float powe(int p);

    24. 23. float operat();

    25. 24.

    26. 25. void cmg88()//关数码管,点阵函数

    27. 26.{

    28. 27. DU=1;

    29. 28. P0=0X00;

    30. 29. DU=0;

    31. 30.}

    32. 31.

    33. 32. #if 0

    34. 33. void main()

    35. 34.{

    36. 35. cmg88();

    37. 36. lcd_1602_init();

    38. 37. delay_1ms();

    39. 38. lcd_1602_write_char(0, 13, '0');

    40. 39.

    41. 40. while(1)

    42. 41. {

    43. 42. while(!keyscan());

    44. 43.

    45. 44. if((key >= '0' && key <= '9') || key == '.') //显示扫描到的数字,不显示运算符号

    46. 45. lcd_1602_write_char(0, str_len, key);

    47. 46.

    48. 47. input[str_len] = key;

    49. 48. str_len ++;

    50. 49. if((key > '9' || key < '0') && key != '.') //扫描到+-/*

    51. 50. {

    52. 51. get_operand(input); //获取操作数

    53. 52. operator[operator_num] = key; //操作码保存在数组中

    54. 53. operator_num ++;

    55. 54. f++;

    56. 55.

    57. 56. if(f>1)

    58. 57. {

    59. 58. operat(); //扫描到2个以上操作码,进行运算

    60. 59. lcd_1602_write_num(1, 0, end); //显示得到的结果

    61. 60. }

    62. 61. }

    63. 62. }

    64. 63.}

    65. 64.

    66. 65./*****************************************************************

    67. 66.函数功能:获取操作数,并将小数点过滤

    68. 67.******************************************************************/

    69. 68.void get_operand(char *string)

    70. 69.{

    71. 70. int i;

    72. 71. char str[20] = {' '};

    73. 72. for(i=0; i<str_len; i++)

    74. 73. {

    75. 74. if((string[i] > '9' || string[i] < '0') && string[i] != '.')

    76. 75. {

    77. 76. str[i] = '\0';

    78. 77. lcd_1602_write_cmd(0x01);

    79. 78. break;

    80. 79. }

    81. 80. str[i] = string[i];

    82. 81. }

    83. 82. str_int(str, operand);

    84. 83. str_len = 0;

    85. 84. operand_num ++;

    86. 85.}

    87. 86./*****************************************************************

    88. 87.函数功能:字符串转浮点数

    89. 88. LCD1602只能显示字符,按键扫描到的也是字符

    90. 89. 所有的字符都必须转换为数字彩能参加运算

    91. 90.******************************************************************/

    92. 91.void str_int(char *str, float num[])

    93. 92.{

    94. 93. int i = 0, len_i = 0, len_f= 1, j = 0;

    95. 94. while(1)

    96. 95. {

    97. 96. if(str[i] == '.')

    98. 97. break;

    99. 98. if(str[i] == '\0')

    100. 99. break;

    101. 100. i++;

    102. 101. }

    103. 102. len_i = i;

    104. 103. while(len_i)

    105. 104. {

    106. 105. num[operand_num] += (str[len_i-1]-'0')*power(10, j);

    107. 106. j++;

    108. 107. len_i--;

    109. 108. }

    110. 109. j = 1;

    111. 110. while(str[i] == '.')

    112. 111. i++;

    113. 112.

    114. 113. while(str[i] != '\0')

    115. 114. {

    116. 115. num[operand_num] += (str[i]-'0')*powe(j);

    117. 116. j++;

    118. 117. i++;

    119. 118. }

    120. 119.}

    121. 120./*****************************************************************

    122. 121.函数功能:求一个数的n次方

    123. 122.******************************************************************/

    124. 123.float power(int num, int p)

    125. 124.{

    126. 125. float sum = 1;

    127. 126.

    128. 127. while(p)

    129. 128. {

    130. 129. sum = sum*num;

    131. 130. p--;

    132. 131. }

    133. 132.

    134. 133. return sum;

    135. 134.}

    136. 135./*****************************************************************

    137. 136.函数功能:求10 的-n次方

    138. 137.******************************************************************/

    139. 138.float powe(int p)

    140. 139.{

    141. 140. float sum = 1;

    142. 141. while(p)

    143. 142. {

    144. 143. sum = sum/10;

    145. 144. p--;

    146. 145. }

    147. 146.

    148. 147. return sum;

    149. 148.}

    150. 149.

    151. 150./*****************************************************************

    152. 151.函数功能:计算过程

    153. 152.******************************************************************/

    154. 153.float operat()

    155. 154.{

    156. 155. if(b == 0)

    157. 156. {

    158. 157. switch (operator[a])

    159. 158. {

    160. 159. case '+':

    161. 160. end = operand[b] + operand[b+1];

    162. 161. break;

    163. 162. case '-':

    164. 163. end = operand[b] - operand[b+1];

    165. 164. break;

    166. 165. case '*':

    167. 166. end = operand[b] * operand[b+1];

    168. 167. break;

    169. 168. case '/':

    170. 169. end = operand[b] / operand[b+1];

    171. 170. break;

    172. 171. default:

    173. 172. break;

    174. 173. }

    175. 174. b = 2;

    176. 175. a++;

    177. 176.

    178. 177. return end;

    179. 178. }

    180. 179. if(b != 0 )

    181. 180. {

    182. 181. switch (operator[a])

    183. 182. {

    184. 183. case '+':

    185. 184. end = end + operand[b];

    186. 185. break;

    187. 186. case '-':

    188. 187. end = end - operand[b];

    189. 188. break;

    190. 189. case '*':

    191. 190. end = end * operand[b];

    192. 191. break;

    193. 192. case '/':

    194. 193. end = end / operand[b];

    195. 194. break;

    196. 195. default:

    197. 196. break;

    198. 197. }

    199. 198. a++;

    200. 199. b++;

    201. 200.

    202. 201. return end;

    203. 202. }

    204. 203.}

    205. 204. #endif





阅读(1842) | 评论(1) | 转发(0) |
1

上一篇:linux操作笔记

下一篇:嵌入式 vi基础命令

给主人留下些什么吧!~~

拾忆17652075852015-08-10 09:38:17

文明上网,理性发言...