加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

STM32的DAC和ADC编程(亮点嵌入式)

(2012-08-21 04:26:28)
标签:

stm32

adc

dac

ra8875

it

分类: 亮点嵌入式

我使用了8个通道的ADC,2个通道的DA

DA使用简单的程序控制发送方式,发送值递增,AD采用连续采样DMA传送方式,获得了成功

液晶连续的显示正确的数值

所有程序在BrightPoint开发板上运行成功,这块屏拿来拿去的打烂了不过还能用哈哈!

http://s10/middle/9cc48191xc7b86b41b649&690

测试方法:DA1连AD1,DA2连AD2 12位AD,精度3.3/4095=8×0.0001,我需要小数点后2位,足够精确

网上部分代码计算公式用 4096是错误的,因为3.3V的时候对应的是4095(12位能表示的最大的数)

函数代码:

void BP_ADC_INIT(void)
{
 ADC_InitTypeDef ADC_InitStructure; 


 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 , ENABLE );   //使能ADC1通道时钟


 
 RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //72M/6=12,ADC最大时间不能超过14M

 //PC   0/ 1/ 2/ 3/ 4/ 5  pb0 1 作为模拟通道输入引脚
 //adc  10 11 12 13 14 15     
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;  //模拟输入引脚
 GPIO_Init(GPIOC, &GPIO_InitStructure);

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;  //模拟输入引脚
 GPIO_Init(GPIOB, &GPIO_InitStructure);
 
 ADC_DeInit(ADC1);  //将外设 ADC1 的全部寄存器重设为缺省值
 
 
 ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作模式:ADC1和ADC2工作在独立模式
 ADC_InitStructure.ADC_ScanConvMode = ENABLE;   //ENABLE 模数转换工作在扫描模式
               //DISABLE  模数转换工作在单次模式
 ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //ENABLE 模数转换工作在连续转换模式
              //DISABLE 模数转换工作在单次转换模式ENABLE
 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动
 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐
 ADC_InitStructure.ADC_NbrOfChannel = ADC_CHANALS; //顺序进行规则转换的ADC通道的数目
 ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器
 
 
 //设置指定ADC的规则组通道,设置它们的转化顺序和采样时间
 //ADC1,ADC通道x,规则采样顺序值为y,采样时间为239.5周期
 ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_239Cycles5 );
 ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 2, ADC_SampleTime_239Cycles5 );
 ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 3, ADC_SampleTime_239Cycles5 );
 ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 4, ADC_SampleTime_239Cycles5 );
 ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 5, ADC_SampleTime_239Cycles5 );
 ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 6, ADC_SampleTime_239Cycles5 );
 ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 7, ADC_SampleTime_239Cycles5 );
 ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 8, ADC_SampleTime_239Cycles5 );
 
  // 开启ADC的DMA支持(要实现DMA功能,还需独立配置DMA通道等参数)
    ADC_DMACmd(ADC1, ENABLE); 
 
 
 ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1
 
 
   
 ADC_ResetCalibration(ADC1); //重置指定的ADC1的校准寄存器
 
 while(ADC_GetResetCalibrationStatus(ADC1)); //获取ADC1重置校准寄存器的状态,设置状态则等待
 
 
 ADC_StartCalibration(ADC1);  //开始指定ADC1的校准状态
 
 while(ADC_GetCalibrationStatus(ADC1));  //获取指定ADC1的校准程序,设置状态则等待
 
 
 //ADC_SoftwareStartConvCmd(ADC1, ENABLE);  //使能指定的ADC1的软件转换启动功能
}

float AD_GetVolt(u16 advalue)  

{
  
   return (float)(advalue * 3.30 / 4095);

}
 void AD_filter(void)
{
   int  sum = 0;
 u8  count,i;   
   for(i=0;i<ADC_CHANALS;i++)

      {

         for ( count=0;count<ADC_TIMES;count++)

          {

             sum += AD_Value[count][i];

          }

          After_filter[i]=sum/ADC_TIMES;

          sum=0;
      }

 }

 void BP_DAC_Init(void)
 {
    DAC_InitTypeDef DAC_InitStructure;
   DAC_DeInit(); 

 
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_4 | GPIO_Pin_5|GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);


    DAC_Cmd(DAC_Channel_1,ENABLE); //
    DAC_Cmd(DAC_Channel_2, ENABLE);

    
    DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;
    DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
  DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude=DAC_TriangleAmplitude_4095;
    DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;
    DAC_Init(DAC_Channel_1, &DAC_InitStructure);
  DAC_Init(DAC_Channel_2, &DAC_InitStructure);
 

 
 }


void BP_DMA_Init(void)
{
 
  DMA_InitTypeDef DMA_InitStructure;
 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);//使能DMA传输

 DMA_DeInit(DMA1_Channel1);   //将DMA的通道1寄存器重设为缺省值
 DMA_InitStructure.DMA_PeripheralBaseAddr =  (u32)&ADC1->DR;  //DMA外设ADC基地址
 DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&AD_Value;  //DMA内存基地址
 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;  //内存作为数据传输的目的地
 DMA_InitStructure.DMA_BufferSize = ADC_TIMES*ADC_CHANALS;  //DMA通道的DMA缓存的大小
 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  //外设地址寄存器不变
 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  //内存地址寄存器递增
 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;  //数据宽度为16位
 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //数据宽度为16位
 DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;  //工作在循环缓存模式
 DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMA通道 x拥有高优先级
 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  //DMA通道x没有设置为内存到内存传输
 DMA_Init(DMA1_Channel1, &DMA_InitStructure);  //根据DMA_InitStruct中指定的参数初始化DMA的通道

}

主程序部分代码:

 if (ADC_SUPPORT)
 {
  BP_ADC_INIT();
  BP_DAC_Init();
  BP_DMA_Init();

 

  DMA_Cmd(DMA1_Channel1, ENABLE);  //启动DMA通道
  daout1=0;
  daout2=0;  

   DAC_SetDualChannelData(DAC_Align_12b_R,daout1,daout2);
      DAC_DualSoftwareTriggerCmd(ENABLE);//
   ADC_SoftwareStartConvCmd(ADC1, ENABLE);

  while(1)  //for 连续
     {

   

      DAC_SetDualChannelData(DAC_Align_12b_R,daout1+=1,daout2+=12);
         DAC_DualSoftwareTriggerCmd(ENABLE);//   
      //while(DAC_GetFlagStatus(, uint32_t DAC_FLAG)
      if (daout1>4095)
          daout1=daout2=0;
    
     // while(ADC_GetSoftwareStartConvStatus(ADC1)==RESET);
      //while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);//等待传输完成否则第一位数据容易丢失      
      ADC_SoftwareStartConvCmd(ADC1, DISABLE);


             AD_filter();
    //  value[0]=AD_GetVolt(After_filter[0]) ;

        for(i=0;i<ADC_CHANALS;i++)
     {

     value[i]= AD_GetVolt(After_filter[i]);
        //if (i<2)
        //printf("value[%d]:\t%d.%dv\n",i,value[i]/100,value[i]0) ;
        delay_ms(10);
     }
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);
    if (LCD_SUPPORT) LcdClear(WHITE);
     if (LCD_SUPPORT) LcdPrintf(35,200,RED,WHITE,"v[0]:%d %4.2fv v[1]:%d %4.2fv",daout1,value[0],daout2,value[1]);
     //Delay100ms(50);
   }

 

效果非常好,程序已经验证!

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有