当前位置:   article > 正文

51单片机课程设计——基于单片机的AD模数转换设计_51单片机ad是什么

51单片机ad是什么
  • 一、功能简介

1.A/D是模拟量到数字量的转换,依靠的是模数转换器(AnalogtoDigitalConverter),简称ADC。D/A是数字量到模拟量的转换,依靠的是数模转换器(DigitaltoAnalogConverter),简称DAC。它们的道理是完全一样的,只是转换方向不同,因此我们讲解过程主要以A/D为例来讲解。

什么是模拟量?就是指变量在一定范围内连续变化的量,总之,任何两个数字之间都有无限个中间值,所以称之为连续变化的量,也就是模拟量。ADC就是起到把连续的信号用离散的数字表达出来的作用。

2.ADC0809的内部逻辑图如图所示:

3. AD各个引脚结构:

D7-D0:8 位数字量输出引脚。

IN0-IN7:8 位模拟量输入引脚。

VCC:+5V 工作电压。

GND:地。

REF(+):参考电压正端。

REF(-):参考电压负端。

START:A/D 转换启动信号输入端。

ALE:地址锁存允许信号输入端。

(以上两种信号用于启动 A/D 转换).

EOC:转换结束信号输出引脚,开始转换时为低电平,当转换结束时为高电平。

OE:输出允许控制端,用以打开三态数据输出锁存器。

CLK:时钟信号输入端(一般为 500KHz)。

二、设计要求

1、用Proteus软件画出电路原理图,在单片机的外部扩展片外总线,并通过片外总线与接口。

2、在ADC0809的某一模拟量输入通道上接外部模拟量。

3、在单片机的外部扩展数码管显示器。

4、分别采用延时与查询的方法编写A/D转换程序。

5、启动A/D转换,将输入模拟量的转换结果在显示器上显示。

三、开发工具介绍

1. Keil MDK-ARM是美国Keil软件公司(现已被ARM公司收购)出品的支持ARM微控制器的一款IDE(集成开发环境)。

MDK-ARM包含了工业标准的Keil C编译器、宏汇编器、调试器、实时内核等组件。具有业行领先的ARM C/C++编译工具链,完美支持Cortex-M、Cortex-R4、ARM7和ARM9系列器件,包含世界上品牌的芯片。比如:ST、Atmel、Freescale、NXP、TI等众多大公司微控制器芯片。

2.Proteus是Lab Center Electronics公司推出的一个EDA工具软件。

Proteus具有原理布图、PCB自动或人工布线、SPICE电路仿真、互动电路仿真、仿真处理器及其外围电路等特点功能。

四、原理图的绘制

五、C程序清单
  1. 1602.h
  2. #include <reg52.h>
  3. #define LCD1602_DB P0
  4. sbit LCD1602_RS = P2^0;
  5. sbit LCD1602_RW = P2^1;
  6. sbit LCD1602_E = P2^2;
  7. void InitLcd1602();
  8. void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
  9. /*
  10. void delay(unsigned int i)
  11. {
  12. while(i--);
  13. }
  14. */
  15. void LcdStar()
  16. {
  17. unsigned char str[] = "Voltage measure";
  18. unsigned char tab[]="Voltage= ";
  19. InitLcd1602();/* 初始化 1602 液晶 */
  20. LcdShowStr(1, 0, str);
  21. LcdShowStr(1, 1, tab);
  22. LcdShowStr(9, 1, "...");//默认初始化温度00
  23. LcdShowStr(13, 1, "V");//添加V电压
  24. }
  25. /* 等待液晶准备好 */
  26. void LcdWaitReady()
  27. {
  28. unsigned char sta;
  29. LCD1602_DB = 0xFF;
  30. LCD1602_RS = 0;
  31. LCD1602_RW = 1;
  32. do {
  33. LCD1602_E = 1;
  34. sta = LCD1602_DB; //读取状态字
  35. LCD1602_E = 0;
  36. } while (sta & 0x80); //bit7 等于 1 表示液晶正忙,重复检测直到其等于 0 为止
  37. }
  38. /* 向 LCD1602 液晶写入一字节命令, cmd-待写入命令值 */
  39. void LcdWriteCmd(unsigned char cmd)
  40. {
  41. LcdWaitReady();
  42. LCD1602_RS = 0;
  43. LCD1602_RW = 0;
  44. LCD1602_DB = cmd;
  45. LCD1602_E = 1;
  46. LCD1602_E = 0;
  47. }
  48. /* 向 LCD1602 液晶写入一字节数据, dat-待写入数据值 */
  49. void LcdWriteDat(unsigned char dat)
  50. {
  51. LcdWaitReady();
  52. LCD1602_RS = 1;
  53. LCD1602_RW = 0;
  54. LCD1602_DB = dat;
  55. LCD1602_E = 1;
  56. LCD1602_E = 0;
  57. }
  58. /* 设置显示 RAM 起始地址,亦即光标位置, (x,y)-对应屏幕上的字符坐标 */
  59. void LcdSetCursor(unsigned char x, unsigned char y)
  60. {
  61. unsigned char addr;
  62. if (y == 0) //由输入的屏幕坐标计算显示 RAM 的地址
  63. addr = 0x00 + x; //第一行字符地址从 0x00 起始
  64. else
  65. addr = 0x40 + x; //第二行字符地址从 0x40 起始
  66. LcdWriteCmd(addr | 0x80); //设置 RAM 地址
  67. }
  68. /* 在液晶上显示字符串, (x,y)-对应屏幕上的起始坐标, str-字符串指针 */
  69. void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str)
  70. {
  71. LcdSetCursor(x, y); //设置起始地址
  72. while (*str != '\0') //连续写入字符串数据,直到检测到结束符
  73. {
  74. LcdWriteDat(*str++); //先取 str 指向的数据,然后 str 自加 1
  75. }
  76. }
  77. /* 初始化 1602 液晶 */
  78. void InitLcd1602()
  79. {
  80. LcdWriteCmd(0x38); //16*2 显示, 5*7 点阵, 8 位数据接口
  81. LcdWriteCmd(0x0C); //显示器开,光标关闭
  82. LcdWriteCmd(0x06); //文字不动,地址自动+1
  83. LcdWriteCmd(0x01); //清屏
  84. }
  1. 测试程序:
  2. #include <reg52.h>
  3. #include <LCD1602.H>
  4. #include <intrins.h>
  5. #define uchar unsigned char
  6. #define uint unsigned int
  7. //ADC0832
  8. sbit CS = P1^0;
  9. sbit CLK = P1^1;
  10. sbit DIO = P1^2;
  11. uchar len;
  12. //一位小数,电压显示
  13. uchar Display_Buffer[4];
  14. //延时
  15. void DelayMS(uint ms)
  16. {
  17. uchar t;
  18. while(ms--)
  19. {
  20. for(t=0;t<120;t++);
  21. }
  22. }
  23. //获取AD转换结果
  24. uchar Get_AD_Result()
  25. {
  26. uchar i,dat1 = 0,dat2 = 0;
  27. //起始控制位
  28. CS = 0;
  29. CLK = 0;
  30. DIO = 1; _nop_(); _nop_();
  31. CLK = 1; _nop_(); _nop_();
  32. //第一个下降沿之前 设DI=1/0
  33. //选择单端/差分(SGL/DIF)模式中的单端输入模式
  34. CLK = 0; DIO=1; _nop_();_nop_();
  35. CLK = 1; _nop_();_nop_();
  36. //第二个下降沿之前 设DI=0/1 选择CH0/CH1
  37. CLK = 0;DIO = 0; _nop_();_nop_();
  38. CLK = 1;DIO = 1; _nop_();_nop_();
  39. //第三个下降沿之前 DI=1
  40. CLK = 0; DIO = 1; _nop_();_nop_();
  41. //4-11,共8个下降沿读取数据(MSB->LSB)
  42. for(i=0;i<8;i++)
  43. {
  44. CLK = 1; _nop_();_nop_();
  45. CLK = 0; _nop_();_nop_();
  46. dat1 = dat1<<1|DIO;
  47. }
  48. //11-18 共8个下降沿读取数据(LSB->MSB)
  49. for(i=0;i<8;i++)
  50. {
  51. dat2 = dat2|((uchar)(DIO)<<i);
  52. CLK = 1; _nop_();_nop_();
  53. CLK = 0; _nop_();_nop_();
  54. }
  55. CS = 1;
  56. //如果MSB->LSB和LSB->MSB读取数据结果相同,返回读取结果,否者0
  57. return (dat1==dat2) ? dat1 : 0 ;
  58. }
  59. void main()
  60. {
  61. uint Data;
  62. InitLcd1602(); //LCD初始化
  63. LcdStar();
  64. DelayMS(10);
  65. while(1)
  66. {
  67. //获取AD转换值 最大值255对应最高电压5.00V
  68. //显示三个数 使用500
  69. Data = Get_AD_Result()*500.0/255;
  70. // 数据分解
  71. Display_Buffer[0]= Data /100+'0';
  72. Display_Buffer[1] = '.';
  73. Display_Buffer[2] = Data /10%10+'0';
  74. Display_Buffer[3] = Data %10+'0';
  75. LcdShowStr(9, 1,Display_Buffer);
  76. }
  77. }

六、实验感想

此次课程设计运用了一些基础的模块比如在课堂上学到的延时、循环和中断,将他们运用到课程设计里可以让我加深对这些知识的印象,有理论依据也要有实践操作。在编写获取AD转换结果时,遇到较多的麻烦,比如在下降沿读取数据时发生错误,Keil报错,根据错误代码通过网络找到了合理的解决方案。

这次课程设计让我意识到课堂中学到的知识只是冰山一角,今后的学习中应当努力掌握知识,提高自己的知识水平,才能做好设计。

七、参考文献

【1】王晋凯 《简简单单学通51单片机开发》.清华大学出版社.2014

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/582740
推荐阅读
相关标签
  

闽ICP备14008679号