你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32F1开发指南笔记30----DAC实验

[复制链接]
STMCU小助手 发布时间:2021-11-27 09:39
本章介绍STM32的DAC功能。本章利用按键(或者USMART)控制STM32内部DAC模块的通道1来输出模拟电压,通过ADC1的通道1采集DAC的输出电压,在LCD模块上面显示ADC获取到的电压值以及DAC的设定输出电压值等信息。

DAC本身是输出,但是为什么端口要设置为模拟输入模式呢?
因为一旦使能DACx通道之后,相应的GPIO引脚(PA4或者PA5)会自动与DAC的模拟输出相连,设置为输入,是为了避免额外的干扰。

2020051417082468.png

20200514170851263.png

20200514171026652.png

20200514171156709.png

2020051417141896.png

20200514171611130.png

20200514171802467.png

20200514171858461.png

20200514171949521.png

20200514172058766.png



硬件设计

20200514172217410.png


main函数
  1. #include "led.h"
  2. #include "delay.h"
  3. #include "key.h"
  4. #include "sys.h"
  5. #include "lcd.h"
  6. #include "usart.h"                  
  7. #include "dac.h"
  8. #include "adc.h"
  9. #include "usmart.h"

  10. int main(void)
  11. {         
  12.         u16 adcx;
  13.         float temp;
  14.          u8 t=0;         
  15.         u16 dacval=0;
  16.         u8 key;
  17.         
  18.         delay_init();                     //延时函数初始化         
  19.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
  20.         uart_init(115200);                 //串口初始化为115200
  21.         KEY_Init();                          //初始化按键程序
  22.          LED_Init();                             //LED端口初始化
  23.         LCD_Init();                                  //LCD初始化
  24.         usmart_dev.init(72);        //初始化USMART        
  25.          Adc_Init();                                  //ADC初始化
  26.         Dac1_Init();                        //DAC初始化

  27.         POINT_COLOR=RED;//设置字体为红色
  28.         LCD_ShowString(60,50,200,16,16,"WarShip STM32");        
  29.         LCD_ShowString(60,70,200,16,16,"DAC TEST");        
  30.         LCD_ShowString(60,90,200,16,16,"ATOM@ALIENTEK");
  31.         LCD_ShowString(60,110,200,16,16,"2015/1/15");        
  32.         LCD_ShowString(60,130,200,16,16,"WK_UP:+  KEY1:-");        
  33.         //显示提示信息                                                                                             
  34.         POINT_COLOR=BLUE;//设置字体为蓝色
  35.         LCD_ShowString(60,150,200,16,16,"DAC VAL:");              
  36.         LCD_ShowString(60,170,200,16,16,"DAC VOL:0.000V");              
  37.         LCD_ShowString(60,190,200,16,16,"ADC VOL:0.000V");
  38.         
  39.         DAC_SetChannel1Data(DAC_Align_12b_R, 0);//初始值为0                          
  40.         
  41.         while(1)
  42.         {
  43.                 t++;
  44.                 key=KEY_Scan(0);                          
  45.                 if(key==WKUP_PRES)
  46.                 {                 
  47.                         if(dacval<4000)dacval+=200;
  48.                  DAC_SetChannel1Data(DAC_Align_12b_R, dacval);//设置DAC值        
  49.                 }else if(key==KEY1_PRES)        
  50.                 {
  51.                         if(dacval>200)dacval-=200;
  52.                         else dacval=0;
  53.                   DAC_SetChannel1Data(DAC_Align_12b_R, dacval);//设置DAC值
  54.                 }         
  55.          
  56.                 if(t==10||key==KEY1_PRES||key==WKUP_PRES) //WKUP/KEY1按下了,或者定时时间到了
  57.                 {        
  58.                         //获取DAC数据
  59.                         adcx=DAC_GetDataOutputValue(DAC_Channel_1);//读取前面设置DAC的值
  60.                         LCD_ShowxNum(124,150,adcx,4,16,0);             //显示DAC寄存器值
  61.                         temp=(float)adcx*(3.3/4096);                        //得到DAC电压值
  62.                         adcx=temp;
  63.                          LCD_ShowxNum(124,170,temp,1,16,0);             //显示电压值整数部分
  64.                          temp-=adcx;
  65.                         temp*=1000;
  66.                         LCD_ShowxNum(140,170,temp,3,16,0X80);         //显示电压值的小数部分
  67.                         
  68.                         //获取ADC数据
  69.                         adcx=Get_Adc_Average(ADC_Channel_1,10);        //得到ADC转换值         
  70.                         temp=(float)adcx*(3.3/4096);                        //得到ADC电压值
  71.                         adcx=temp;
  72.                          LCD_ShowxNum(124,190,temp,1,16,0);             //显示电压值整数部分
  73.                          temp-=adcx;
  74.                         temp*=1000;
  75.                         LCD_ShowxNum(140,190,temp,3,16,0X80);         //显示电压值的小数部分
  76.                         LED0=!LED0;           
  77.                         t=0;
  78.                 }            
  79.                 delay_ms(10);        
  80.         }
  81. }
复制代码

dac.c函数
  1. #include "dac.h"

  2. //DAC通道1输出初始化
  3. void Dac1_Init(void)
  4. {
  5.         GPIO_InitTypeDef GPIO_InitStructure;
  6.         DAC_InitTypeDef DAC_InitType;

  7.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE );          //使能PORTA通道时钟
  8.            RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE );          //使能DAC通道时钟

  9.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;                                  //端口配置
  10.          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;                            //模拟输入
  11.          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  12.          GPIO_Init(GPIOA, &GPIO_InitStructure);
  13.         GPIO_SetBits(GPIOA,GPIO_Pin_4)        ;//PA.4 输出高
  14.                                        
  15.         DAC_InitType.DAC_Trigger=DAC_Trigger_None;        //不使用触发功能 TEN1=0
  16.         DAC_InitType.DAC_WaveGeneration=DAC_WaveGeneration_None;//不使用波形发生
  17.         DAC_InitType.DAC_LFSRUnmask_TriangleAmplitude=DAC_LFSRUnmask_Bit0;//屏蔽、幅值设置
  18.         DAC_InitType.DAC_OutputBuffer=DAC_OutputBuffer_Disable ;        //DAC1输出缓存关闭 BOFF1=1
  19.     DAC_Init(DAC_Channel_1,&DAC_InitType);         //初始化DAC通道1

  20.         DAC_Cmd(DAC_Channel_1, ENABLE);  //使能DAC1

  21.     DAC_SetChannel1Data(DAC_Align_12b_R, 0);  //12位右对齐数据格式设置DAC值
  22. }

  23. //设置通道1输出电压
  24. //vol:0~3300,代表0~3.3V
  25. void Dac1_Set_Vol(u16 vol)
  26. {
  27.         float temp=vol;
  28.         temp/=1000;
  29.         temp=temp*4096/3.3;
  30.         DAC_SetChannel1Data(DAC_Align_12b_R,temp);//12位右对齐数据格式设置DAC值
  31. }
复制代码

adc.c函数
  1. #include "adc.h"
  2. #include "delay.h"
  3.                   
  4. //初始化ADC
  5. //这里我们仅以规则通道为例
  6. //我们默认将开启通道0~3                                                                                                                                          
  7. void  Adc_Init(void)
  8. {         
  9.         ADC_InitTypeDef ADC_InitStructure;
  10.         GPIO_InitTypeDef GPIO_InitStructure;

  11.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1, ENABLE );          //使能ADC1通道时钟

  12.         RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M

  13.         //PA1 作为模拟通道输入引脚                        
  14.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
  15.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;                //模拟输入引脚
  16.         GPIO_Init(GPIOA, &GPIO_InitStructure);        

  17.         ADC_DeInit(ADC1);  //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值

  18.         ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;        //ADC工作模式:ADC1和ADC2工作在独立模式
  19.         ADC_InitStructure.ADC_ScanConvMode = DISABLE;        //模数转换工作在单通道模式
  20.         ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;        //模数转换工作在单次转换模式
  21.         ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;        //转换由软件而不是外部触发启动
  22.         ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;        //ADC数据右对齐
  23.         ADC_InitStructure.ADC_NbrOfChannel = 1;        //顺序进行规则转换的ADC通道的数目
  24.         ADC_Init(ADC1, &ADC_InitStructure);        //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器   

  25.         ADC_Cmd(ADC1, ENABLE);        //使能指定的ADC1
  26.         
  27.         ADC_ResetCalibration(ADC1);        //使能复位校准  
  28.          
  29.         while(ADC_GetResetCalibrationStatus(ADC1));        //等待复位校准结束
  30.         
  31.         ADC_StartCalibration(ADC1);         //开启AD校准

  32.         while(ADC_GetCalibrationStatus(ADC1));         //等待校准结束
  33. }        


  34. //获得ADC值
  35. //ch:通道值 0~3
  36. u16 Get_Adc(u8 ch)   
  37. {
  38.           //设置指定ADC的规则组通道,一个序列,采样时间
  39.         ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 );        //ADC1,ADC通道,采样时间为239.5周期                                      

  40.         ADC_SoftwareStartConvCmd(ADC1, ENABLE);                //使能指定的ADC1的软件转换启动功能        
  41.          
  42.         while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束

  43.         return ADC_GetConversionValue(ADC1);        //返回最近一次ADC1规则组的转换结果
  44. }

  45. u16 Get_Adc_Average(u8 ch,u8 times)
  46. {
  47.         u32 temp_val=0;
  48.         u8 t;
  49.         for(t=0;t<times;t++)
  50.         {
  51.                 temp_val+=Get_Adc(ch);
  52.                 delay_ms(5);
  53.         }
  54.         return temp_val/times;
  55. }         
复制代码

从 main 函数代码可以看出,按键设置输出电压的时候,每次都是以 0.161V 递增或递减的,而通过 USMART 调用 Dac1_Set_Vol 函数,则可以实现任意电平输出控制(当然得在 DAC 可控范围内)。


收藏 评论0 发布时间:2021-11-27 09:39

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版