终于逮了个忙里偷闲的机会,就再学一下LPC1768的外围功能吧,循序渐进是学习的基本规则,也许LPC1768的DAC与8位单片机16位单片机里面集成的DAC操作类似,但是既然这是懒猫的学习日志,就顺便把DAC再好好复习一下了,或许能品出个什么味来^_^DAC是Digital to Analog Converter的缩写,中文名就是数模转换器,D/A转换器一般由数码寄存器、模拟电子开关电路、解码网络、求和电路及基准电压等几部分组成。如下图所示:

图1-1 DAC原理框图

数字量以串行或并行方式输入,存储于数码寄存器中,数码寄存器输出的名位数码分别控制对应的模拟开关,使数码为1的位在位权网络上产生与其值成正比的电流值或电压值,再由求和电路将各权值相加,即得到数字量对应的模拟量。按解码网络结构不同可以将DAC转换器分成T          型电阻网络D/A转换器、倒T型电阻网络D/A转换器、权电流D/A转换器、权电阻网络转换器。

1、  T型电阻网络D/A转换器,其简单模型如下图所示:

图1-2 T型电阻网络D/A转换器模型

2、  倒T型电阻网络D/A转换器简易模型

图1-3 倒T型电阻网络D/A转换器

3、  权电流D/A转换器简易模型如下图所示:

图1-4  权电流D/A转换器简易模型

4、  权电阻网络转换器简易模型如下图所示:

图 1-5 权电阻网络转换器简易模型

按模拟电子开关的电路的不同,也可以将D/A转换器分为CMOS开关型D/A转换器(速度要求不高),双极型D/A转换器。而双极型D/A转换器双可以划分为电流开关型(速度要求较高)与ECL电流开关型(转换速度更高)两种。如果对欧姆定律不陌生的话,我想上面各个模型是如何输出电压的应该就可以理解了,在这里就不总结公式了,因为这只是模型,对应,实际电路与模型是有所出入的,在实际应用中要着重关注一下以下几个参数:

1、  分辨率

D/A转换器的分辨率用最小分辨电压VLSB与满量程输出电压VFSV的比值来表示:

从上式可以看出D/A转换器的分辨率只与输入二进制数的位数n有关,因此大部分情况下我们直接把n做为分辨率如8位,10位,12位等,由此我们也可以知道分辨率值越小,分辨能力越高。

2、  转换精度

在D/A转换器中,一般用转换误差来描述转换精度。DAC转换误差是指实际输出模拟电压值与理想值的最大偏差。转换误差是一个综合性的静态指标,主要由三部分构成:

1)非线性误差:一般是由于模拟电子开关的导通电阻和导通压降及R、2R电阻值的偏差引起。

2)漂移误差:一般是由于运算放大器的零点漂移引起。

3)增益误差:一般是由于参考电压偏离标准值、运放增益不稳定引起。

3、  转换速度

转换速度一般由建立时间决定,从输入由全0突变全1起,到输出电压稳定(最大输出电压正负二分之一最小输出电压)止,称为DAC转换时间。它是DAC最大响应时间。例如,DAC5G7520响应时间不大于500ns。

除了以上三个常见的指标D/A转换器的指标还包括电源抑制比、功率消耗、温度系数以及输入高、低逻辑电平的数值等技术指标。关于D/A的应用,应该说在电子系统中应用相当广泛,除了在微机系统中将数字量转换为模拟量典型应用之外,还常用于波形生成,名种数字式的或编程应用等。

好了,关于D/A转换器的知识暂时总结到这,更深入的知道还需要翻一下模电,信号与线性系统(好像里面有奈奎斯特定理,与采样有关),微电子,放大器等方面的书籍。下面简单总结一下LPC1768内部集成的D/A转换器。LPC1768内部集成的是10位模数转换器,它是电阻串联结构的,并且带有缓冲输出,最大输出频率为1MHz。电阻串联结构模型如下图所示:

图 1-6 电阻串联结构

涉及到D/A的引脚主要有DAC输出脚P0.26,参考电压引脚,用来给D/A转换器提供参考电压,模拟电源与数字电源VDD/VSS,这个两个电源要分开提供,再不使用DAC时也要将这两个引脚连接到电源,不能悬空,不然系统会不稳定。

DAC的配置也很简单,首先就是将P0.26设置为DAC模式,再一个就是配置DAC控制寄存器DACDR。DAC的控制寄存器DACDR的6-15位是DAC的输出电压数字值,这个数字决定了要输出的电压大小,DAC输出电压的计算方法是:

公式中VDAC即指AC的控制寄存器DACDR的6-15位的值,VREF指的是参考电压,在这次实验电路中用的是3.3V。LPC1768的DAC功能还有DAM中断和定时控制功能,它采用又缓冲方式输出。在这里简单总结一下DAM模式,所谓的DAM模式也就是Direct Memory Access,汉语的意思就是直接内存访问,是一种不经过CPU而直接从内存存取数据的数据交换模式。在DMA模式下,CPU只须向DMA控制器下达指令,让DMA控制器来处理数据的传送,数据传送完毕再把信息反馈给CPU,这样就很大程度上减轻了CPU资源占有率,可以大大节省系统资源。DMA模式又可以分为Single-Word DMA(单字节DMA)和Multi-Word DMA(多字节DMA)两种,其中所能达到的最大传输速率也只有16.6MB/s。DMA有两个技术特征,首先是直接传送,其次是块传送。

DMA工作过程

⑴     当进程要求设备输入数据时,CPU把准备存放输入数据的内存起始地址以及要传送的字节数分别送入DMA控制器中的内存地址寄存器和传送字节计数器。

⑵     发出数据传输要求的进行进入等待状态。此时正在执行的CPU指令被暂时挂起。进程调度程序调度其他进程占据CPU。

⑶     输入设备不断地窃取CPU工作周期,将数据缓冲寄存器中的数据源源不断地写入内存,直到所要求的字节全部传送完毕。

⑷     DMA控制器在传送完所有字节时,通过中断请求线发出中断信号。CPU在接收到中断信号后,转入中断处理程序进行后续处理。

⑸     中断处理结束后,CPU返回到被中断的进程中,或切换到新的进程上下文环境中,继续执行。

DMA与中断的区别

⑴     中断方式是在数据缓冲寄存器满之后发出中断,要求CPU进行中断处理,而DMA方式则是在所要求传送的数据块全部传送结束时要求CPU 进行中断处理。这就大大减少了CPU进行中断处理的次数。

⑵     中断方式的数据传送是在中断处理时由CPU控制完成的,而DMA方式则是在DMA控制器的控制下,不经过CPU控制完成的。这就排除了CPU因并行设备过多而来不及处理以及因速度不匹配而造成数据丢失等现象。

在DMA方式中,由于I/O设备直接同内存发生成块的数据交换,因此I/O效率比较高。由于DMA技术可以提高I/O效率,因此在现代计算机系统中,得到了广泛的应用。许多输入输出设备的控制器,特别是块设备的控制器,都支持DMA方式。

通过上述分析可以看出,DMA控制器功能的强弱,是决定DMA效率的关键因素。DMA控制器需要为每次数据的传送做大量的工作,数据传送单位的增大意味着传送次数的减少。另外,DMA方式窃取了时钟周期,CPU处理效率降低了,要想尽量少地窃取时钟周期,就要设法提高DMA控制器的性能,这样可以较少地影响CPU出理效率。

好了,关于DAM的知识先总结到这,要想使用LPC1768的DAM功能,需要配置D/A转换控制寄存器DACCTRL与DAC转换计数寄存器DACCNTVAL。这次实验只是简单的学习怎样使用DAC,所以没有用到DAM。下面说一下实验电路,就是把DAC转换的电压通过放大器输出到Speaker,电压值不同,则Speaker的响度就不一样,如下图所示:

图 1-7 DAC实验电路图

关于LM386M已经是烂大街的芯片,关于它的应用网上有成大堆的资料可供参考,这里就不总结它的用法了,下面贴上这次实验的程序:

一、dac.c程序源代码

  1. /*********************************************************************************
  2. 文件名称:dac.c
  3. 功 能: 关于DAC的一些函数
  4. 编译环境: MDKV4.12
  5. 时 钟: 外部12Mhz
  6. 日 期: 11/09/08
  7. 作 者: 懒猫爱飞
  8. 备 注:NULL
  9. ---------------------------------------------------------------------------------
  10. 修改内容:NULL
  11. 修改日期:XXXX年xx月xx日 xx时xx分
  12. 修改人员:xxx xxx xxx
  13.  
  14. **********************************************************************************/
  15. #include"includes.h"
  16.  
  17. /********************************************************************************
  18. * 函数名称 :void DACInit( void )
  19. * 函数功能 : DAC初始化
  20. * 入口参数 : 无
  21. * 出口参数 : 无
  22. * 备 注 :无
  23. *******************************************************************************/
  24. void DACInit( void )
  25. {
  26. PINCON -> PINSEL1 = 0x00200000; /* 设置 p0.26 为DAC输出脚 */
  27. }
  28.  
  29. void DacOut(unsigned int val)
  30. {
  31. DAC -> DACR = ((val << )/) | DAC_BIAS;
  32. }

二、main.c程序部分源代码

  1. /*********************************************************************************
  2. 工程名称:lesson5
  3. 功 能: 学习使用LPC1768的DAC功能
  4. 编译环境: MDKV4.12
  5. 时 钟: 外部12Mhz
  6. 日 期: 11/09/08
  7. 作 者: 懒猫爱飞
  8. 版本 号:V1R0
  9. ---------------------------------------------------------------------------------
  10. 修改内容:NULL
  11. 修改日期:
  12. 修改人员:
  13. ---------------------------------------------------------------------------------
  14.  
  15. **********************************************************************************/
  16.  
  17. /*********************************************************************************
  18. 文件名称:mian.c
  19. 功 能: 主要调度函数及应用函数
  20. 编译环境: MDKV4.12
  21. 时 钟: 外部12Mhz
  22. 日 期: 11/09/08
  23. 作 者: 懒猫爱飞
  24. 备 注:NULL
  25. ---------------------------------------------------------------------------------
  26. 修改内容:NULL
  27. 修改日期:XXXX年xx月xx日 xx时xx分
  28. 修改人员:xxx xxx xxx
  29.  
  30. **********************************************************************************/
  31. #include"includes.h"
  32.  
  33. volatile unsigned long SysTickCnt; /* 用于系统时钟计数 */
  34.  
  35. unsigned char LedOnMeg[] = "Led 1 On!\r\n";
  36. unsigned char LedOffMeg[] = "Led all Off!\r\n";
  37. unsigned char KeyMeg[] = "key push down \r\n";
  38. unsigned char DacVal[] = "the voltage is: 0.0 V \r\n";
  39. unsigned ] = {
  40. "**********************************************\r\n",
  41. "**** --欢迎光临-- ****\r\n",
  42. "**** 小野兽的小草窝^_^ ****\r\n",
  43. "**** http://blog.ednchina.com/ytfdhb/ ****\r\n",
  44. "**** 我是懒猫爱飞,我的口号是: ****\r\n",
  45. "**** 每天进步一点点,开心多一点^_^ ****\r\n",
  46. "**********************************************\r\n"
  47. };
  48.  
  49. unsigned ; /* 按键状态 */
  50. unsigned ; /* 按键当前状态值 */
  51. unsigned ; /* 按键前一个状态值 */
  52. unsigned ;
  53.  
  54. unsigned ; /* 状态计数 */
  55.  
  56. /********************************************************************************
  57. * 函数名称 :void SysTick_Handler (void)
  58. * 函数功能 : 系统节拍定时器中断函数,每1ms计数一次
  59. * 入口参数 : 无
  60. * 出口参数 : 无
  61. * 备 注 :无
  62. *******************************************************************************/
  63. void SysTick_Handler (void)
  64. {
  65. SysTickCnt++;
  66. }
  67.  
  68. /********************************************************************************
  69. * 函数名称 :void Delay (unsigned long tick)
  70. * 函数功能 : 毫秒级延时函数
  71. * 入口参数 : unsigned long tick -- 延时时长
  72. * 出口参数 : 无
  73. * 备 注 :无
  74. *******************************************************************************/
  75. void DelayMs (unsigned long tick)
  76. {
  77. unsigned long systickcnt;
  78.  
  79. systickcnt = SysTickCnt;
  80. while ((SysTickCnt - systickcnt) < tick);
  81. }
  82. /********************************************************************************
  83. * 函数名称 :void PortInit(void)
  84. * 函数功能 : 端口初始化
  85. * 入口参数 : 无
  86. * 出口参数 : 无
  87. * 备 注 :无
  88. *******************************************************************************/
  89. void PortInit(void)
  90. {
  91. GPIO1->FIODIR = 0xB0000000; /* LEDs on PORT1 defined as Output */
  92. GPIO2->FIODIR = 0x0000007C; /* LEDs on PORT2 defined as Output */
  93. LedAllOff(); /* 初始化时熄灭所有的灯 */
  94. }
  95.  
  96. /********************************************************************************
  97. * 函数名称 :void KeyScan(void)
  98. * 函数功能 : 按键扫描
  99. * 入口参数 : 无
  100. * 出口参数 : 无
  101. * 备 注 :现在只扫描一个按键
  102. *******************************************************************************/
  103. void KeyScan()
  104. {
  105. key_pre = KEY_EN ;
  106. if(!KEY_EN ) /* 如果按键按下 */
  107. {
  108. if(key_old)
  109. {
  110. ) /* 下降沿有效 */
  111. {
  112. key_sta = ; /* 记录按键状态 */
  113. }
  114. }
  115. }
  116. key_old = key_pre;
  117. }
  118.  
  119. /********************************************************************************
  120. * 函数名称 :void KeyHandle(void)
  121. * 函数功能 : 按键处理函数
  122. * 入口参数 : 无
  123. * 出口参数 : 无
  124. * 备 注 :无
  125. *******************************************************************************/
  126. void KeyHandle(void)
  127. {
  128. )
  129. {
  130. StepCnt++; /* 执行下一步*/
  131. )
  132. {
  133. UART0_SendString (LedOffMeg); /* 显示LED状态信息 */
  134. }
  135. )
  136. {
  137. LedOnMeg[] = StepCnt+0x30; /* 转换成字符 */
  138. UART0_SendString (LedOnMeg); /* 显示LED状态信息 */
  139. }
  140. key_sta = ; /* 按键状态清零,保证只执行一次 */
  141. }
  142. }
  143. /********************************************************************************
  144. * 函数名称 :void LedHandle()
  145. * 函数功能 : LED灯处理函数
  146. * 入口参数 : 无
  147. * 出口参数 : 无
  148. * 备 注 :无
  149. *******************************************************************************/
  150. void LedHandle()
  151. {
  152. switch(StepCnt)
  153. {
  154. :Led1On(); /* LED1 点亮*/
  155. break;
  156. :Led2On(); /* LED2 点亮*/
  157. break;
  158. :Led3On(); /* LED3 点亮*/
  159. break;
  160. :Led4On(); /* LED4 点亮*/
  161. break;
  162. :Led5On(); /* LED5 点亮*/
  163. break;
  164. :Led6On(); /* LED6 点亮*/
  165. break;
  166. :Led7On(); /* LED7 点亮*/
  167. break;
  168. :Led8On(); /* LED8 点亮*/
  169. break;
  170. :LedAllOff(); /* 熄灭所有的LED灯*/
  171. StepCnt = ; /* 重新开始 */
  172. break;
  173. default:break;
  174. }
  175. }
  176. /********************************************************************************
  177. * 函数名称 :void DacConver(unsigned int val)
  178. * 函数功能 : DAC转换函数
  179. * 入口参数 : unsigned int val -- 要转换的电压值,单位mv
  180. * 出口参数 : 无
  181. * 备 注 :无
  182. *******************************************************************************/
  183. void DacConver(unsigned int val)
  184. {
  185.  
  186. unsigned ;
  187. unsigned ;
  188. hi = val/; /* 求电压的整数部分 */
  189. low = val%/; /* 求电压的小数部分 */
  190. DacVal[]= (unsigned char)hi + 0x30; /* 将电压值转换成字符,方便从串口发送 */
  191. DacVal[]= (unsigned char)low + 0x30;/* 将电压值转换成字符,方便从串口发送 */
  192. DacOut(val); /* 赋给DAC控制寄存器DACDR的值*/
  193. UARTSend(,DacVal,); /* 发送转换信息 */
  194. }
  195.  
  196. /********************************************************************************
  197. * 函数名称 :int main(void)
  198. * 函数功能 : 主函数
  199. * 入口参数 : 无
  200. * 出口参数 : 无
  201. * 备 注 :无
  202. *******************************************************************************/
  203. int main(void)
  204. {
  205. unsigned ;
  206. SystemInit(); /* 系统初始化,函数在system_LPC17xx.c文件夹中定义 */
  207. SysTick_Config(SystemFrequency/ - );/* 配置节拍定时器中断,每1ms中断一次 */
  208.  
  209. PortInit(); /* 端口初始化 */
  210. DACInit();
  211.  
  212. UARTInit(,); /* 设置串口0波特率 */
  213. ;i<;i++)
  214. {
  215. UARTSend(,OpenString[i],); /* 发送欢迎信息 */
  216. }
  217. /* 下面的函数是测试DAC的,分别输出2.0V、2.5V、3.0V与3.3V*/
  218. DacConver(); // 2.0v
  219. DacConver(); // 2.5v
  220. DacConver(); // 3.0v
  221. DacConver(); // 3.0v
  222.  
  223. //LedOnMeg[4] = 4+0x30; /* 转换成字符 */
  224. //UART0_SendString (KeyMeg);
  225. )
  226. {
  227. KeyScan(); // 按键扫描
  228. KeyHandle(); // 按键处理
  229. LedHandle(); // Led处理程序
  230. }
  231. }

Cortex-M3学习日志(五) -- DAC实验的更多相关文章

  1. stm32和cortex M3学习内核简单总结

    1.stm32综述 2.寄存器组 3.操作模式和特权级别 4.存储器映射 5.中断和异常 6.其他 Stm32综述 这可以说是我第一款认真学习的单片机了,学完这个就要开启我通往arm9的大门了,接下来 ...

  2. Cortex-M3学习日志(六) -- ADC实验

    上一次简单的总结了一下DAC方面的知识,好吧,这次再来总结一下ADC方面的东东.ADC即Analog-to-Digital Converter的缩写,指模/数转换器或者模拟/数字转换器.现实世界是由模 ...

  3. STM32学习之路入门篇之指令集及cortex——m3的存储系统

    STM32学习之路入门篇之指令集及cortex——m3的存储系统 一.汇编语言基础 一).汇编语言:基本语法 1.汇编指令最典型的书写模式: 标号 操作码        操作数1, 操作数2,... ...

  4. 第五周实验报告&学习总结

    实验三 String类的应用 实验目的 掌握类String类的使用: 学会使用JDK帮助文档: 实验内容 1.已知字符串:"this is a test of java".按要求执 ...

  5. 文本分类学习 (五) 机器学习SVM的前奏-特征提取(卡方检验续集)

    前言: 上一篇比较详细的介绍了卡方检验和卡方分布.这篇我们就实际操刀,找到一些训练集,正所谓纸上得来终觉浅,绝知此事要躬行.然而我在躬行的时候,发现了卡方检验对于文本分类来说应该把公式再变形一般,那样 ...

  6. Java IO学习笔记五:BIO到NIO

    作者:Grey 原文地址: Java IO学习笔记五:BIO到NIO 准备环境 准备一个CentOS7的Linux实例: 实例的IP: 192.168.205.138 我们这次实验的目的就是直观感受一 ...

  7. 20145330《Java程序设计》第五次实验报告

    20145330<Java程序设计>第五次实验报告 实验五 Java网络编程及安全 实验内容 1.掌握Socket程序的编写: 2.掌握密码技术的使用: 3.设计安全传输系统 4.结队伙伴 ...

  8. ARM 架构、ARM7、ARM9、STM32、Cortex M3 M4 、51、AVR 之间有什么区别和联系?(转载自知乎)

    ARM架构:  由英国ARM公司设计的一系列32位的RISC微处理器架构总称,现有ARMv1~ARMv8种类. ARM7:       一类采用ARMv3或ARMv4架构的,使用冯诺依曼结构的内核. ...

  9. 20135302魏静静——linux课程第五周实验及总结

    linux课程第五周实验及总结 一.学习总结 给MenuOS增加time和time-asm命令(四步操作命令) rm menu -rf 强制删除git clone http://github.com/ ...

随机推荐

  1. BZOJ 3233: [Ahoi2013]找硬币( dp )

    dp(x)表示最大面值为x时需要的最少硬币数. 枚举x的质因数p,  dp(x) = min( dp(x/p) - (p-1) * sigma[a[i]/x] ). ----------------- ...

  2. CentOS上编译安装Git

    1. 安装(编译安装)软件 # 先安装git依赖的包 yum install zlib-devel yum install openssl-devel yum install perl yum ins ...

  3. html5的video标签支持的视频格式

  4. 用Cookie和Session实现用户登录 函数

    由于网页是一种无状态的连接程序,你无法得知用户的浏览状态,必须通过Cookie或Session记录用户的有关信息. Cookie: 是一种在远程浏览器端储存数据并以此来跟踪和识别用户的机制. PHP透 ...

  5. 在Linux手动把文件转码的方法,防止乱码出现

    iconv -f utf-8 -t gb2312 report.html  >  report_test.html

  6. 1011. A+B和C

    /* * Main.c * 1011. A+B和C * Created on: 2014年8月30日 * Author: Boomkeeper *********测试通过******* */ #inc ...

  7. [Django] Windows 下安装 配置Pinax 工程

    Pinax 是一个基于Django开发的脚手架,有一些现成的模板和功能模块可以使用,方便快速有效的开发一个Django项目.下面举个例子如何安装一个pinax项目到集成开发环境Aptana里面. 先从 ...

  8. vimTAB宽度等设置

    10 set shiftwidth=4 11 set softtabstop=4 12 set textwidth=200 13 set nu 14 set autoindent 15 set noe ...

  9. centos6.5 Eclipse C/C++开发环境及项目创建测试

    1,新建C++ project

  10. 【COM学习】之二、HRESULT,GUID

    HRESULT 来向用户报告各种情况.   他的值位于  WINERROR.H中 QueryInterface返回一个HRESULT值. HRESULT不是一个句柄,他是一个可分成三个域的32位值. ...