aopeng 发表于 2021-3-5 11:12:58

大工20秋《单片机原理及应用》复习资料十六

单片机原理及应用辅导资料十六主    题:课件第八章第4-5节
学习时间:2020年7月13日--7月19日
“不忘初心、牢记使命”主题理论学习:
每周文摘:我们党要始终成为时代先锋、民族脊梁,始终成为马克思主义执政党,自身必须始终过硬。全党要更加自觉地坚定党性原则,勇于直面问题,敢于刮骨疗毒,消除一切损害党的先进性和纯洁性的因素,清除一切侵蚀党的健康肌体的病毒,不断增强党的政治领导力、思想引领力、群众组织力、社会号召力,确保我们党永葆旺盛生命力和强大战斗力。
摘选自《决胜全面建成小康社会,夺取新时代中国特色社会主义伟大胜利》课程内容:
我们这周主要学习课件第八章实验第4-5节的相关内容。希望通过下面的内容能使同学们加深对单片机实验相关知识的理解。一、学习要求
了解STM32 ADC和DAC的使用方法。二、主要内容
1.ADC实验
STM32拥有1-3个ADC(STM32F101/102系列只有1个ADC),这些ADC可以独立使用,也可以使用双重模式(提高采样率)。STM32的ADC是12位逐次逼近型的模拟数字转换器。它有18个通道,可测量16个外部和2个内部信号源。各通道的A/D转换可以单次、连续、扫描或间断模式执行。ADC的结果可以左对齐或右对齐方式存储在16位数据寄存器中。模拟看门狗特性允许应用程序检测输入电压是否超出用户定义的高/低阀值。
STM32F103系列最少都拥有2个ADC,我们选择的STM32F103RCT包含有3个ADC。STM32的ADC最大的转换速率为1Mhz,也就是转换时间为1us(在ADCCLK=14M,采样周期为1.5个ADC时钟下得到),不要让ADC的时钟超过14M,否则将导致结果准确度下降。
STM32将ADC的转换分为2个通道组:规则通道组和注入通道组。规则通道相当于你正常运行的程序,而注入通道呢,就相当于中断。在你程序正常执行的时候,中断是可以打断你的执行的。同这个类似,注入通道的转换可以打断规则通道的转换,在注入通道被转换完成之后,规则通道才得以继续转换。
STM32的ADC在单次转换模式下,只执行一次转换,该模式可以通过ADC_CR2寄存器的ADON位(只适用于规则通道)启动,也可以通过外部触发启动(适用于规则通道和注入通道),这时CONT位为0。
以规则通道为例,一旦所选择的通道转换完成,转换结果将被存在ADC_DR寄存器中,EOC(转换结束)标志将被置位,如果设置了EOCIE,则会产生中断。然后ADC将停止,直到下次启动。
本实验所使用到的寄存器有:
①ADC_CR1和ADC_CR2寄存器

图1 ADC_CR1寄存器各位描述
ADC_CR1的SCAN位,用于设置扫描模式,由软件设置和清除,如果设置为1,则使用扫描模式,如果为0,则关闭扫描模式。在扫描模式下,由ADC_SQRx或ADC_JSQRx寄存器选中的通道被转换。如果设置了EOCIE或JEOCIE,只在最后一个通道转换完毕后才会产生EOC或JEOC中断。
ADC_CR1用于设置ADC的操作模式,详细的对应关系如图2所示:

图2 ADC操作模式
本章我们要使用的是独立模式,所以设置这几位为0就可以了。ADC_CR2寄存器的各位描述如图3所示:

图3 ADC_CR2寄存器操作模式
ADON位用于开关AD转换器。而CONT位用于设置是否进行连续转换,我们使用单次转换,所以CONT位必须为0。CAL和RSTCAL用于AD校准。ALIGN用于设置数据对齐,我们使用右对齐,该位设置为0。
EXTSEL用于选择启动规则转换组转换的外部事件,详细的设置关系如图4所示:

图4 ADC选择启动规则转换事件设置
我们这里使用的是软件触发(SWSTART),所以设置这3个位为111。ADC_CR2的SWSTART位用于开始规则通道的转换,我们每次转换(单次转换模式下)都需要向该位写1。AWDEN为用于使能温度传感器和Vrefint。STM32内部的温度传感器我们将在下一节介绍。
②ADC采样事件寄存器(ADC_SMPR1和ADC_SMPR2)
这两个寄存器用于设置通道0~17的采样时间,每个通道占用3个位。ADC_SMPR1的各位描述如图5所示:

图5ADC_SMPR1寄存器各位描述
ADC_SMPR2的各位描述如下图6所示:

图6ADC_SMPR2寄存器各位描述
对于每个要转换的通道,采样时间建议尽量长一点,以获得较高的准确度,但是这样会降低ADC的转换速率。ADC的转换时间可以由以下公式计算:
Tcovn=采样时间+12.5个周期
其中:Tcovn为总转换时间,采样时间是根据每个通道的SMP位的设置来决定的。例如,当ADCCLK=14Mhz的时候,并设置1.5个周期的采样时间,则得到:Tcovn=1.5+12.5=14个周期=1us。
③ADC规则序列寄存器(ADC_SQR1~3)
该寄存器总共有3个,这几个寄存器的功能都差不多,这里我们仅介绍一下ADC_SQR1,该寄存器的各位描述如图7所示:

图7 ADC_SQR1寄存器各位描述
L用于存储规则序列的长度,我们这里只用了1个,所以设置这几个位的值为0。其他的SQ13~16则存储了规则序列中第13~16通道的编号(编号范围:0~17)。另外两个规则序列寄存器同ADC_SQR1大同小异,我们这里就不再介绍了,要说明一点的是:我们选择的是单次转换,所以只有一个通道在规则序列里面,这个序列就是SQ1,通过ADC_SQR3的最低5位(也就是SQ1)设置。
④ADC规则数据寄存器(ADC_DR)
规则序列中的AD转化结果都将被存在这个寄存器里面,而注入通道的转换结果被保存在ADC_JDRx里面。ADC_DR的各位描述如图8:

图8ADC_JDRx寄存器各位描述
这里要提醒一点的是,该寄存器的数据可以通过ADC_CR2的ALIGN位设置左对齐还是右对齐。在读取数据的时候要注意。
⑤ADC寄存器为ADC状态寄存器(ADC_SR),该寄存器保存了ADC转换时的各种状态。该寄存器的各位描述如图9所示:

图9ADC_SR寄存器各位描述
这里我们要用到的是EOC位,我们通过判断该位来决定是否此次规则通道的AD转换已经完成,如果完成我们就从ADC_DR中读取转换结果,否则等待转换完成。本实验使用ADC1的通道1来进行AD转换,其详细设置步骤如下:
1)开启PA口时钟,设置PA1为模拟输入。
STM32F103RCT6的ADC通道1在PA1上,所以,我们先要使能PORTA的时钟,然后设置PA1为模拟输入。
2)使能ADC1时钟,并设置分频因子。
要使用ADC1,第一步就是要使能ADC1的时钟,在使能完时钟之后,进行一次ADC1的复位。接着我们就可以通过RCC_CFGR设置ADC1的分频因子。分频因子要确保ADC1的时钟(ADCCLK)不要超过14Mhz。
3)设置ADC1的工作模式。
在设置完分频因子之后,我们就可以开始ADC1的模式配置了,设置单次转换模式、触发方式选择、数据对齐方式等都在这一步实现。
4)设置ADC1规则序列的相关信息。
接下来我们要设置规则序列的相关信息,我们这里只有一个通道,并且是单次转换的,所以设置规则序列中通道数为1(ADC_SQR1=0000),然后设置通道1的采样周期(通过ADC_SMPR2设置)。
5)开启AD转换器,并校准。
在设置完了以上信息后,我们就开启AD转换器,执行复位校准和AD校准,注意这两步是必须的!不校准将导致结果很不准确。
6)读取ADC值。
在上面的校准完成之后,ADC就算准备好了。接下来我们要做的就是设置规则序列1里面的通道(通过ADC_SQR3设置),然后启动ADC转换。在转换结束后,读取ADC1_DR里面的值就是了。
这里还需要说明一下ADC的参考电压,MiniSTM32开发板使用的是STM32F103RCT6,该芯片没有外部参考电压引脚,ADC的参考电压直接取自VDDA,也就是3.3V。本实验用到的硬件资源有:
1)指示灯DS0
2)TFTLCD模块
3)ADC
4)杜邦线
ADC属于STM32内部资源,实际上我们只需要软件设置就可以正常工作,不过我们需要在外部连接其端口到被测电压上面。本章,我们通过ADC1的通道1(PA1)来读取外部电压值,MiniSTM32开发板没有设计参考电压源在上面,但是板上有几个可以提供测试的地方:1,3.3V电源。2,GND。3,后备电池。注意:这里不能接到板上5V电源上去测试,这可能会烧坏ADC!。
因为要连接到其他地方测试电压,所以我们需要一根杜邦线,或者自备的连接线也可以,一头插在PA1排针上(在P3上),另外一头就接你要测试的电压点(确保该电压不大于3.3V即可)。如果是测量外部电压,则还需要和开发板共地,开发板上有很多GND 的排针,随便连接一个共地即可。
程序代码
#include "adc.h"
//初始化ADC
//这里我们仅以规则通道为例
//我们默认仅开启通道1
voidAdc_Init(void)
{   
RCC->APB2ENR|=1<<2;    //使能PORTA口时钟
GPIOA->CRL&=0XFFFFFF0F;//PA1 anolog输入
RCC->APB2ENR|=1<<9;    //ADC1时钟使能
RCC->APB2RSTR|=1<<9;   //ADC1复位
RCC->APB2RSTR&=~(1<<9);//复位结束
RCC->CFGR&=~(3<<14);   //分频因子清零
//SYSCLK/DIV2=12M ADC时钟设置为12M,ADC最大时钟不能超过14M!
//否则将导致ADC准确度下降!
RCC->CFGR|=2<<14;      
ADC1->CR1&=0XF0FFFF; //工作模式清零
ADC1->CR1|=0<<16;   //独立工作模式
ADC1->CR1&=~(1<<8);//非扫描模式
ADC1->CR2&=~(1<<1);   //单次转换模式
ADC1->CR2&=~(7<<17);
ADC1->CR2|=7<<17;//软件控制转换
ADC1->CR2|=1<<20;//使用用外部触发(SWSTART)!!!必须使用一个事件来触发
ADC1->CR2&=~(1<<11);   //右对齐
ADC1->SQR1&=~(0XF<<20);
ADC1->SQR1|=0<<20;    //1个转换在规则序列中也就是只转换规则序列1
//设置通道1的采样时间
ADC1->SMPR2&=~(7<<3); //通道1采样时间清空
ADC1->SMPR2|=7<<3;    //通道1239.5周期,提高采样时间可以提高精确度
ADC1->CR2|=1<<0;//开启AD转换器
ADC1->CR2|=1<<3;       //使能复位校准
while(ADC1->CR2&1<<3); //等待校准结束
//该位由软件设置并由硬件清除。在校准寄存器被初始化后该位将被清除。
ADC1->CR2|=1<<2;      //开启AD校准
while(ADC1->CR2&1<<2);//等待校准结束
}
//获得ADC值
//ch:通道值0~16
//返回值:转换结果
u16 Get_Adc(u8 ch)   
{
//设置转换序列
ADC1->SQR3&=0XFFFFFFE0;//规则序列1 通道ch
ADC1->SQR3|=ch;
ADC1->CR2|=1<<22;       //启动规则转换通道
while(!(ADC1->SR&1<<1));//等待转换结束
return ADC1->DR;//返回adc值
}
//获取通道ch的转换值,取times次,然后平均
//ch:通道编号
//times:获取次数
//返回值:通道ch的times次转换结果平均值
u16 Get_Adc_Average(u8 ch,u8 times)
{
u32 temp_val=0;u8 t;
for(t=0;t<times;t++){temp_val+=Get_Adc(ch);delay_ms(5);}
return temp_val/times;
}
此部分代码就3个函数,Adc_Init函数用于初始化ADC1。这里基本上是按我们上面的步骤来初始化的,我们仅开通了1个通道,即通道1。第二个函数Get_Adc,用于读取某个通道的ADC值,例如我们读取通道1上的ADC值,就可以通过Get_Adc(1)得到。最后一个函数Get_Adc_Average,用于多次获取ADC值,取平均,用来提高准确度。
保存adc.c代码,并将该代码加入HARDWARE组下。接下来在adc.h文件里面输入如下代码:
#ifndef __ADC_H
#define __ADC_H
#include "sys.h"
#define ADC_CH11 //通道1
void Adc_Init(void); //ADC通道初始化
u16Get_Adc(u8 ch); //获得某个通道值
u16 Get_Adc_Average(u8 ch,u8 times);//得到某个通道10次采样的平均值
#endif
该部分代码很简单,这里我们就不多说了,这里定义ADC_CH1为1,即通道1的编号宏定义,我们在main函数将会用到这个宏定义。接下来我们在test.c里面,修改main函数如下:
int main(void)
{
u16 adcx;float temp;
Stm32_Clock_Init(9);//系统时钟设置
uart_init(72,9600);//串口初始化为9600
delay_init(72);//延时初始化
LED_Init();//初始化与LED连接的硬件接口
LCD_Init();//初始化LCD
Adc_Init();//ADC初始化
POINT_COLOR=RED;//设置字体为红色
LCD_ShowString(60,50,200,16,16,"Mini STM32");
LCD_ShowString(60,70,200,16,16,"ADC TEST");
LCD_ShowString(60,90,200,16,16,"ATOM@ALIENTEK");
LCD_ShowString(60,110,200,16,16,"2014/3/9");
//显示提示信息
POINT_COLOR=BLUE;//设置字体为蓝色
LCD_ShowString(60,130,200,16,16,"ADC_CH0_VAL:");
LCD_ShowString(60,150,200,16,16,"ADC_CH0_VOL:0.000V");
while(1)
{
adcx=Get_Adc_Average(ADC_CH1,10);
LCD_ShowxNum(156,130,adcx,4,16,0);//显示ADC的值
temp=(float)adcx*(3.3/4096);
adcx=temp;
LCD_ShowxNum(156,150,adcx,1,16,0);//显示电压值
temp-=adcx;
temp*=1000;
LCD_ShowxNum(172,150,temp,3,16,0X80);
LED0=!LED0;delay_ms(250);
}
}
此部分代码,我们在TFTLCD模块上显示一些提示信息后,将每隔250ms读取一次ADC通道0的值,并显示读到的ADC值(数字量),以及其转换成模拟量后的电压值。同时控制LED0闪烁,以提示程序正在运行。2.DAC实验
大容量的STM32F103具有内部DAC,MiniSTM32选择的是STM32F103RCT6属于大容量产品,所以是带有DAC模块的。
STM32的DAC模块(数字/模拟转换模块)是12位数字输入,电压输出型的DAC。DAC可以配置为8位或12位模式,也可以与DMA控制器配合使用。DAC工作在12位模式时,数据可以设置成左对齐或右对齐。DAC模块有2个输出通道,每个通道都有单独的转换器。在双DAC模式下,2个通道可以独立地进行转换,也可以同时进行转换并同步地更新2个通道的输出。
STM32的DAC模块主要特点有:
①2个DAC转换器:每个转换器对应1个输出通道
②8位或者12位单调输出
③12位模式下数据左对齐或者右对齐
④同步更新功能
⑤噪声波形生成
⑥三角波形生成
⑦双DAC通道同时或者分别转换
⑧每个通道都有DMA功能单个DAC通道的框图如图10所示:

图10 DAC通道模块框图
图中VDDA和VSSA为DAC模块模拟部分的供电,Vref+是参考电压输入引脚,不过我们使用的STM32F103RCT6,只有64引脚,没有Vref引脚,参考电压直接来自VDDA,也就是固定为3.3V。DAC_OUTx就是DAC的输出通道了(对应PA4或者PA5引脚)。
从图10可以看出,DAC输出是受DORx寄存器直接控制的,但是我们不能直接往DORx寄存器写入数据,而是通过DHRx间接的传给DORx寄存器,实现对DAC输出的控制。前面我们提到,STM32的DAC支持8/12位模式,8位模式的时候是固定的右对齐的,而12位模式又可以设置左对齐/右对齐。单DAC通道x,总共有3种情况:
① 8位数据右对齐:用户将数据写入DAC_DHR8Rx位(实际是存入DHRx位)。
② 12位数据左对齐:用户将数据写入DAC_DHR12Lx位(实际是存入DHRx位)。
③ 12位数据右对齐:用户将数据写入DAC_DHR12Rx位(实际是存入DHRx位)。
我们本章使用的就是单DAC通道1,采用12位右对齐格式,所以采用第③种情况。
如果没有选中硬件触发(寄存器DAC_CR1的TENx位置’0’),存入寄存器DAC_DHRx的数据会在一个APB1时钟周期后自动传至寄存器DAC_DORx。如果选中硬件触发(寄存器DAC_CR1的TENx位置’1’),数据传输在触发发生以后3个APB1时钟周期后完成。一旦数据从DAC_DHRx寄存器装入DAC_DORx寄存器,在经过时间之后,输出即有效,这段时间的长短依电源电压和模拟输出负载的不同会有所变化。我们可以从STM32F103RCT6的数据手册查到的典型值为3us,最大是4us。所以DAC的转换速度最快是250K左右。
本实验要用到的寄存器有:
DAC控制寄存器DAC_CR,该寄存器的各位描述如图11所示:

图11 寄存器DAC_CR各位描述
DAC_CR的低16位用于控制通道1,而高16位用于控制通道2,我们这里仅列出比较重要的最低8位的详细描述,如图12所示:

图12 寄存器DAC_CR低八位详细描述
首先,我们来看DAC通道1使能位(EN1),该位用来控制DAC通道1使能的,本章我们就是用的DAC通道1,所以该位设置为1。
再看关闭DAC通道1输出缓存控制位(BOFF1),这里STM32的DAC输出缓存做的有些不好,如果使能的话,虽然输出能力强一点,但是输出没法到0,这是个很严重的问题。所以本章我们不使用输出缓存。即设置该位为1。
DAC通道1触发使能位(TEN1),该位用来控制是否使用触发,里我们不使用触发,所以设置该位为0。
DAC通道1触发选择位(TSEL1),这里我们没用到外部触发,所以设置这几个位为0就行了。
DAC通道1噪声/三角波生成使能位(WAVE1),这里我们同样没用到波形发生器,故也设置为0即可。
DAC通道1屏蔽/复制选择器(MAMP),这些位仅在使用了波形发生器的时候有用,本章没有用到波形发生器,故设置为0就可以了。
最后是DAC通道1 DMA使能位(DMAEN1),本章我们没有用到DMA功能,故还是设置为0。
通道2的情况和通道1一模一样,这里就不不细说了。在DAC_CR设置好之后,DAC就可以正常工作了,我们仅需要再设置DAC的数据保持寄存器的值,就可以在DAC输出通道得到你想要的电压了(对应IO口设置为模拟输入)。本章,我们用的是DAC通道1的12位右对齐数据保持寄存器:DAC_DHR12R1,该寄存器各位描述如图13所示:

图13 寄存器DAC_DHR12R1各位描述
该寄存器用来设置DAC输出,通过写入12位数据到该寄存器,就可以在DAC输出通道1(PA4)得到我们所要的结果。
本实验我们将使用DAC模块的通道1来输出模拟电压,其详细设置步骤如下:
1)开启PA口时钟,设置PA4为模拟输入。
STM32F103RCT6的DAC通道1是接在PA4上的,所以,我们先要使能PORTA的时钟,然后设置PA4为模拟输入(虽然是输入,但是STM32内部会连接在DAC模拟输出上)。
2)使能DAC1时钟。
同其他外设一样,要想使用,必须先开启相应的时钟。STM32的DAC模块时钟是由APB1提供的,所以我们先要在APB1ENR寄存器里面设置DAC模块的时钟使能。
3)设置DAC的工作模式。
该部分设置全部通过DAC_CR设置实现,包括:DAC通道1使能、DAC通道1输出缓存关闭、不使用触发、不使用波形发生器等设置。
4)设置DAC的输出值。
通过前面3个步骤的设置,DAC就可以开始工作了,我们使用12位右对齐数据格式,所以我们通过设置DHR12R1,就可以在DAC输出引脚(PA4)得到不同的电压值了。本实验用到的硬件资源有:
1)指示灯DS0
2)WK_UP和KEY0按键
3)串口
4)TFTLCD模块
5)ADC
6)DAC
本实验我们使用DAC通道1输出模拟电压,然后通过ADC1的通道1对该输出电压进行读取,并显示在LCD模块上面,DAC的输出电压,我们通过按键(或USMART)进行设置。
我们需要用到ADC采集DAC的输出电压,所以需要在硬件上把他们短接起来。ADC和DAC的连接原理图如图14所示:
图14 ADC、DAC与STM32连接原理图
如上图所示,我们只需要通过杜邦线将PA4和PA1连接起来就可以了。软件代码
#include "dac.h"
//DAC通道1输出初始化
void Dac1_Init(void)
{
RCC->APB2ENR|=1<<2;   //使能PORTA时钟
RCC->APB1ENR|=1<<29;//使能DAC时钟
GPIOA->CRL&=0XFFF0FFFF;
GPIOA->CRL|=0X00000000;//PA4 模拟输入
DAC->CR|=1<<0;//使能DAC1
DAC->CR|=1<<1;//DAC1输出缓存不使能BOFF1=1
DAC->CR|=0<<2;//不使用触发功能TEN1=0
DAC->CR|=0<<3;//DAC TIM6 TRGO,不过要TEN1=1才行
DAC->CR|=0<<6;//不使用波形发生
DAC->CR|=0<<8;//屏蔽、幅值设置
DAC->CR|=0<<12;//DAC1 DMA不使能
DAC->DHR12R1=0;
}
//设置通道1输出电压
//vol:0~3300,代表0~3.3V
void Dac1_Set_Vol(u16 vol)
{
float temp=vol;temp/=1000;
temp=temp*4096/3.3;
DAC->DHR12R1=temp;
}
此部分代码就2个函数,Dac1_Init函数用于初始化DAC通道1。这里基本上是按我们上面的步骤来初始化的,经过这个初始化之后,我们就可以正常使用DAC通道1了。第二个函数Dac1_Set_Vol,用于设置DAC通道1的输出电压,通过USMART调用该函数,就可以随意设置DAC通道1的输出电压了。
保存dac.c代码,并将该代码加入HARDWARE组下。接下来在dac.h文件里面输入如下代码:
#ifndef __DAC_H
#define __DAC_H
#include "sys.h"
void Dac1_Init(void);//DAC通道1初始化
void Dac1_Set_Vol(u16 vol);//设置通道1输出电压
#endif
该部分代码很简单,这里我们就不多说了。接下来我们在test.c里面,修改main函数如下:
int main(void)
{
u16 adcx;u16 dacval=0;
float temp;u8 t=0;u8 key;
Stm32_Clock_Init(9);//系统时钟设置
uart_init(72,9600);//串口初始化为9600
delay_init(72);//延时初始化
LED_Init();//初始化与LED连接的硬件接口
LCD_Init();//初始化LCD
KEY_Init();//按键初始化
Adc_Init();//ADC初始化
Dac1_Init();//DAC通道1初始化
usmart_dev.init(72);//USMART初始化
POINT_COLOR=RED;//设置字体为红色
LCD_ShowString(60,50,200,16,16,"Mini STM32");
LCD_ShowString(60,70,200,16,16,"DAC TEST");
LCD_ShowString(60,90,200,16,16,"ATOM@ALIENTEK");
LCD_ShowString(60,110,200,16,16,"2014/3/9");
LCD_ShowString(60,130,200,16,16,"WK_UP:+KEY0:-");
//显示提示信息
POINT_COLOR=BLUE;//设置字体为蓝色
LCD_ShowString(60,150,200,16,16,"DAC VAL:");
LCD_ShowString(60,170,200,16,16,"DAC VOL:0.000V");
LCD_ShowString(60,190,200,16,16,"ADC VOL:0.000V");
DAC->DHR12R1=dacval;//初始值为0
while(1)
{ t++;
key=KEY_Scan(0);
if(key==WKUP_PRES)
{
if(dacval<4000)dacval+=200;
DAC->DHR12R1=dacval;//输出
}else if(key==KEY0_PRES)
{
if(dacval>200)dacval-=200;
else dacval=0;
DAC->DHR12R1=dacval; //输出
}
if(t==10||key==KEY0_PRES||key==WKUP_PRES) //WKUP/KEY0/时间到
{
adcx=DAC->DHR12R1;
LCD_ShowxNum(124,150,adcx,4,16,0);   //显示DAC寄存器值
temp=(float)adcx*(3.3/4096);//得到DAC电压值
adcx=temp;
LCD_ShowxNum(124,170,temp,1,16,0);   //显示电压值整数部分
temp-=adcx;temp*=1000;
LCD_ShowxNum(140,170,temp,3,16,0X80); //显示电压值的小数部分
adcx=Get_Adc_Average(ADC_CH1,10);//得到ADC转换值
temp=(float)adcx*(3.3/4096);//得到ADC电压值
adcx=temp;
LCD_ShowxNum(124,190,temp,1,16,0);   //显示电压值整数部分
temp-=adcx;temp*=1000;
LCD_ShowxNum(140,190,temp,3,16,0X80); //显示电压值的小数部分
LED0=!LED0;t=0;
}
delay_ms(10);
}
}
此部分代码,我们先对需要用到的模块进行初始化,然后显示一些提示信息,本章我们通过WK_UP和KEY0来实现对DAC输出的幅值控制。按下WK_UP增加,按KEY0减小。同时在LCD上面显示DHR12R1寄存器的值、DAC设计输出电压以及ADC采集到的DAC输出电压。
转载注明无忧答案网QQ 761296021
页: [1]
查看完整版本: 大工20秋《单片机原理及应用》复习资料十六