【STC8A8K64D4开发板】第2-17讲:PCA实现数模转换(DAC)

第2-17讲:PCA实现数模转换(DAC)

    1. 学习目的
  1. 了解DAC数模转换原理及RC积分电路原理。
  2. 掌握STC8A8K64D4系列单片机实现DAC功能的硬件和软件设计。
    1. DAC简介

DAC (全称是Digital to Analog Convertor)数模转换器是一种将数字信号转换为模拟信号(以电流、电压或)的设备或电路。在很多数字系统中(例如计算机、单片机),信号以数字方式(0或者1)存储和传输,而数模转换器DAC可以将这样的信号转换为模拟信号,从而使得他们能够被外界(人或其他非数字系统)识别。数模转换器DAC的常见用法是在音乐播放器中将数字形式存储的音频信号输出为模拟的声音。

T型电阻网络方式是一种常见的DAC实现方法,由T型电阻网络和运算放大器组成,下图是8位DAC的原理示意图。输入数字量中的每位都按其权值分别转换为模拟量,之后通过运算放大器求和相加。

图1:T型电阻网络示意图

上图中,由于运算放大器的反相输入端为“虚地”,所以无论模拟开关连接到“0”还是 “1”,从T形电阻网络节点对“地”往右看的等效电阻均为R,由此可计算出基准电流I=VREF/R。再根据电流可计算出流过各个分支的电流从右向左(I0~I7)依次是I/2、I/4、I/8、I/16、I/32、I/64、I/128和、I/256。

由此,每一位数字量都发挥了有效的位权,流向运算放大器反相输入端的总电流如下: 

该电流经过运算放大器换成模拟电压输出,从而实现由数字信号到模拟信号的转换。这里以8位DAC示例,输出电压有256种变化,当然,这种T形电阻网络的转换原理可以推广到n位,实现n位DAC。

市面上很多单片机片内集成了DAC外设,并且也有专用独立DAC芯片供用户选择使用,那为什么还需要使用PWM实现DAC?

这是因为虽然市面上很多集成了DAC的单片机和独立DAC芯片,他们使用起来更方便,并且精度也高,但是很多时候,我们并不需要很高的精度,我们选择使用的单片机可能没有DAC外设,但是一般都有PWM,因此,出于对成本的考虑,我们会使用PWM实现DAC,从而节省成本。

    1. 硬件电路设计

STC8A8K64D4系列单片机片内没有集成DAC外设,因此,IK-64D4开发板通过PCA工作于PWM模式输出高速PWM脉冲配合RC滤波电路实现DAC功能。

实现DAC转换是基于将高速PWM信号通过RC电路整合成比较平缓的电压信号作为模拟输出,通过改变高速PWM信号的占空比达到改变输出电平信号幅度的目的。为了达到比较理想的电压信号输出,P7.0口输出的PWM信号经二阶RC滤波电路整合,如下图所示。

图2:PWM实现DAC电路

  • 注:开发板J27端子需使用短路帽短接P06和DAC_O以及P70和DAC_I,并且将J27端子的P06和ADC以及P70和DHT11的短路帽去掉。

    1. 软件设计
      1. PWM实现DAC实验
  • 注:本节的实验是在“实验2-11-1:ADC采样电位器电压(查询方式)”的基础上修改,本节对应的实验源码是:“实验2-17-1: PWM实现DAC实验”。
  • 关于PWM的内容,读者可以参阅《第2-16讲:可编程计数器阵列PCA》中的PCA实现PWM部分的内容。
        1. 实验内容

配置PCA模块0工作于PWM模式, PCA配置如下:

  1. 系统时钟:24MHz。
  2. PCA时钟源:系统时钟= 24Mhz。
  3. 功能引脚:P7.0。
  4. 中断:不开启中断。
  5. PWM位数:8位。

程序运行后,在主循环中不断改变PWM的占空比,从而改变P7.0输出的电压值。实验中为了方便观察实验现象,配置P0.6为ADC功能引脚,并通过跳线帽将其连接到DAC电路的输出端,这样,就可以实时获取DAC输出的电压值并通过串口输出,以便于我们观察实验现象(DAC输出电压值的改变)。

        1. 代码编写
  1. 新建一个名称为“pca.c”的文件及其头文件“pca.h”并保存到工程的“Source”文件夹,并将“pca.c”加入到Keil工程中的“SOURCE”组。
  2. 引用头文件

因为在“pca.c”文件中使用了“pca.c”文件中的函数,所以需要引用下面的头文件“pca.h”。

代码清单:引用头文件

  1. //引用pca的头文件  
  2. #include   " pca.h"  
  1. PCA初始化

本例中,我们配置PCA模块0工作于PWM模式,PCA时钟源使用系统时钟(24Mhz),功能引脚为P7.0,代码清单如下。

代码清单:PCA初始化

  1.  /*************************************************************************** 
  2.  * 描  述 : PCA初始化 
  3.  * 入  参 : 无 
  4.  * 返回值 : 无 
  5.  **************************************************************************/  
  6. void pca_init(void)  
  7. {  
  8.    CCON = 0x00;        //CF、CR、CCF1、CCF0位均清零  
  9.        
  10.    P_SW1 &= 0xEF;      //PCA模块0功能引脚选择P7.0              
  11.    P_SW1 |= 0x20;                    
  12.    /*--------------------PCA模式寄存器CMOD配置--------------------------- 
  13.      位7  位6  位5  位4   位3~位1    位0 
  14.      CIDL   x    x    x    CPS[2~0]    BCF 
  15.       0     x    x    x      100       0 
  16.      
  17.     CIDL=0:空闲模式下仍然计数 
  18.     CPS[2~0]=100:PCA时钟源选择:系统时钟 
  19.     BCF=0:禁止PCA计数器溢出中断 
  20.    -----------------------------END------------------------------------*/  
  21.    CMOD = 0x08;   
  22.    CL = 0x00;          //PCA计数器赋初值  
  23.    CH = 0x00;          //PCA计数器赋初值  
  24.       
  25.    IP &= ~0x02;        //中断优先级配置为2(较高优先级)    
  26.    IPH |= 0x02;  
  27.     /*------------------PCA模块0模式控制寄存器CCAPM0配置------------------ 
  28.     位7   位6    位5    位4     位3    位2   位1    位0 
  29.      x   ECOM0  CCAPP0  CCAPN0   MAT0   TOG0  PWM0   ECCF0 
  30.      x     0      0       0       0      0     1       0  
  31.      
  32.     ECOM0=0:关闭PCA模块0的比较功能 
  33.     CCAPP0=0:关闭PCA模块0的上升沿捕获 
  34.     CCAPN0=0:关闭PCA模块0的下降沿捕获 
  35.     MAT0=0:关闭PCA模块0的匹配功能 
  36.     TOG0=0:关闭PCA模块0的高速脉冲输出功能 
  37.     PWM0=1:开启PCA模块0的脉宽调制输出功能 
  38.     ECCF0=0:禁止PCA模块0的匹配/捕获中断 
  39.    -----------------------------END------------------------------------*/
  40.    CCAPM0 = 0x02;
  41.       
  42.    PCA_PWM0 &= 0x3F;               //PCA模块0工作于8位PWM功能  
  43.    PCA_PWM0 &= 0xFC;               //EPC0H位和EPC0L位置0  
  44.    CCAP0L = 0x00;            //PCA比较值寄存器赋初值        
  45.    CCAP0H = 0x00;            //PCA比较值寄存器赋初值   
  46.    CR = 1;                   //启动PCA计数器阵列计数    
  47. }  
  1. 主函数

主函数中初始化PCA和ADC,PCA计数启动后,在主循环中不断改变PWM的占空比,使得DAC输出不同的电压。

ADC采样DAC输出的电压值后,通过串口输出采样值及其对应的电压值,代码清单如下。

代码清单:主函数

  1. /*************************************************************************** 
  2.  * 描  述 : 主函数 
  3.  * 入  参 : 无 
  4.  * 返回值 : 无 
  5.  **************************************************************************/  
  6. int main(void)  
  7. {  
  8.    u16 adc_value;  //存放ADC采样值  
  9.    float voltage;  //存放ADC采样值计算后的电压值  
  10.    u16 TempData;  
  11.       
  12.    P2M1 &= 0xBF;   P2M0 &= 0xBF;     //设置P2.6为准双向口(LED1)  
  13.    P3M1 &= 0xFE;   P3M0 &= 0xFE;     //设置P3.0为准双向口(串口1的RxD)  
  14.    P3M1 &= 0xFD;   P3M0 |= 0x02;     //设置P3.1为推挽输出(串口1的TxD)  
  15.    P7M1 &= 0xFE;   P7M0 |= 0x01;     //设置P7.0为推挽输出  
  16.       
  17.    pca_init();  
  18.    uart1_init();                 //串口1初始化  
  19.    adc_config();                 //初始化ADC    
  20.    EA = 1;                       //使能总中断  
  21.       
  22.    while(1)  
  23.    {  
  24.       TempData++;  
  25.       CCAP0H = (u8)(256 - TempData);      //P7.0引脚输出频率不变但占空比不断变化的脉冲信号  
  26.       if(TempData>138)TempData=1;          //占空比达到很大时重新设定占空比
  27.       delay_ms(5);   
  28.       adc_value = get_adc_value();                  //读取ADC采样值  
  29.       voltage   = (2.5*adc_value)/4096;               //将ADC采样值转换为电压(单位V)  
  30.       printf("ADC采样值: %d\r\n",adc_value);       //串口打印上传的采集的原始值  
  31.       printf("采样值对应的电压:%.2fV\r\n",voltage);//串口打印ADC采样电压  
  32.       delay_ms(200);                                //延时200ms,方便观察数据  
  33.       led_toggle(LED_1);  //翻转指示灯D1状态,指示一次ADC采样完成  
  34.    }  
  35. }  
        1. 硬件连接

本实验通过P7.0输出PWM信号实现DAC输出,P0.6配置为ADC用于采样DAC电路输出的电压,按照下图所示连接跳线帽。

图3:硬件连接

        1. 实验步骤
  1. 解压“…\第3部分:配套例程源码”目录下的压缩文件“实验2-17-1: PWM实现DAC实验”,将解压后得到的文件夹拷贝到合适的目录,如“D\STC8”(这样做的目的是为了防止中文路径或者工程存放的路径过深导致打开工程出现问题)。
  2. 双击“…\pca_dac\project”目录下的工程文件“pca_dac.uvproj”。
  3. 点击编译按钮编译工程,编译成功后生成的HEX文件“pca_dac.hex”位于工程的“…\pca_dac\Project\Object”目录下。
  4. 打开STC-ISP软件下载程序,下载使用内部IRC时钟,IRC频率选择:24MHz。
  5. 电脑上打开串口调试助手,选择开发板对应的串口号,将波特率设置为9600bps。程序运行后,在串口接收窗口可以看到开发板上报的ADC采样值及其对应的电压值,如下图所示。

图4:串口调试助手中观察电压值

  • 25
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
好的,以下是STC8A8K64D4单片机与JDY-31蓝牙模块进行通信的基本代码: ```c #include <STC8.H> #include <intrins.h> #define FOSC 24000000L //系统时钟频率 #define BAUD 9600 //串口波特率 #define MD0 P3_0 //定义STC8A8K64D4 P3.0引脚作为蓝牙模块的模式选择引脚 bit busy; //串口忙标志位 unsigned char RcvBuff; //串口接收缓冲区 void InitUART() //初始化串口 { SCON = 0x50; //8位数据,可变波特率 TMOD &= 0x0F; //清除原来的定时器设置 TMOD |= 0x20; //设定定时器1为8位自动重装方式 TH1 = TL1 = -(FOSC/12/32/BAUD);//设定波特率 TR1 = 1; //启动定时器1 ES = 1; //串口中断允许 EA = 1; //总中断允许 } void UART_SendByte(unsigned char dat) //串口发送一个字符 { while(busy); //等待前面的数据发送完成 busy = 1; SBUF = dat; //写数据到UART数据寄存器 } void main() { InitUART(); //初始化串口 while(1) { MD0 = 0; //将P3.0引脚置为低电平,使蓝牙模块进入AT指令模式 UART_SendByte('A'); //向蓝牙模块发送AT指令 MD0 = 1; //将P3.0引脚置为高电平,使蓝牙模块退出AT指令模式 } } void UART_Isr() interrupt 4 using 1 //串口中断服务程序 { if(RI) { RI = 0; RcvBuff = SBUF; } if(TI) { TI = 0; busy = 0; } } ``` 以上代码实现了串口初始化、发送一个字符的函数以及主函数中对蓝牙模块的AT指令操作。其中,P3.0引脚作为蓝牙模块的模式选择引脚,当该引脚为低电平时,蓝牙模块进入AT指令模式;当该引脚为高电平时,蓝牙模块退出AT指令模式。此外,还需要注意将STC8A8K64D4单片机的串口接口连接到JDY-31蓝牙模块的TX和RX引脚上。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

电子友人张

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值