OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 13105|回复: 7

关于stm32的ADC,DMA的寄存器版本程序的一个问题

[复制链接]

30

主题

156

帖子

0

精华

高级会员

Rank: 4

积分
783
金钱
783
注册时间
2012-6-14
在线时间
206 小时
发表于 2012-6-27 16:25:36 | 显示全部楼层 |阅读模式
    原子大哥的寄存器版本的例程中,操作ADC的时候,没有使用DMA例程,所以,今天我自己将DMA和ADC两个寄存器版本的程序融合在一起,主要还是为了加深自己对这个的理解,但是出现了问题,请大家看一下,能帮忙找一下不?红色是我添加和修改的部分。
   主要修改 程序如下:
1,dma.c中修改的地方:
void MYDMA_Config(DMA_Channel_TypeDef*DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
{
u32 DR_Base;  //做缓冲用,不知道为什么.非要不可
RCC->AHBENR|=1<<0;//开启DMA1时钟
DR_Base=cpar;
DMA_CHx->CPAR=DR_Base; //DMA1 外设地址 
DMA_CHx->CMAR=(u32)cmar; //DMA1,存储器地址
DMA1_MEM_LEN=cndtr;      //保存DMA传输数据量
DMA_CHx->CNDTR=cndtr;    //DMA1,传输数据量
DMA_CHx->CCR=0X00000000;//复位

DMA_CHx->CCR|=1<<1;    //允许传输完中断

DMA_CHx->CCR|=0<<4;  //从外设读
DMA_CHx->CCR|=1<<5;  //循环模式
DMA_CHx->CCR|=0<<6;  //外设地址非增量模式
DMA_CHx->CCR|=1<<7;  //存储器增量模式
DMA_CHx->CCR|=1<<8;  //外设数据宽度为16位
DMA_CHx->CCR|=1<<10; //存储器数据宽度16位
DMA_CHx->CCR|=1<<12; //中等优先级
DMA_CHx->CCR|=0<<14; //非存储器到存储器模式  

///设定中断
MY_NVIC_Init(1,3,DMA1_Channel1_IRQChannel ,2);    

2,adc.c中修改的地方:
void  Adc_Init(void)
{    
//1,先初始化IO口
///ADC通道0 在PA0上,所以,我们先要使能 PORTA的时钟,然后设置PA0为模拟输入。 
  RCC->APB2ENR|=1<<2;    //使能PORTA口时钟 
GPIOA->CRL&=0XFFFF0000;//PA0 1 2 3 anolog输入
//通道10/11设置
///使能ADC1 时钟,并设置分频因子。 
RCC->APB2ENR|=1<<9;    //ADC1时钟使能 ///1:ADC1接口时钟开启  
RCC->APB2RSTR|=1<<9;   //ADC1复位 ///1:复位ADC1 接口
RCC->APB2RSTR&=~(1<<9);//复位结束    
RCC->CFGR&=~(3<<14);   //分频因子清零 ///00:PCLK2 2分频后作为ADC时钟 
//SYSCLK/DIV2=12M ADC时钟设置为12M,ADC最大时钟不能超过14M!
//否则将导致ADC准确度下降! 
RCC->CFGR|=2<<14;       ///10:PCLK2 6分频后作为ADC时钟,这里应该是12mhz

///3,设置ADC1 的工作模式
ADC1->CR1&=0XF0FFFF;   //工作模式清零
ADC1->CR1|=0<<16;      //独立工作模式  
ADC1->CR1&=(1<<8);    //扫描模式  
ADC1->CR2&=(1<<1);    //连续转换模式
ADC1->CR2|=1<<8;        //启用DMA   
ADC1->CR2&=~(7<<17);   
ADC1->CR2|=7<<17;   //软件控制转换   ///111 :SWSTART
ADC1->CR2|=1<<20;      //使用用外部触发(SWSTART)!!! 必须使用一个事件来触发 ///1:使用外部事件启动转换
ADC1->CR2&=~(1<<11);   //右对齐 ///0:右对齐
ADC1->SQR1&=~(0XF<<20); ///0000:1个转换
ADC1->SQR1&=0<<20;     //1个转换在规则序列中 也就是只转换规则序列1  ///0000:1个转换

//4,设置通道0~3的采样时间
ADC1->SMPR2&=0XFFFFF000;//通道0,1,2,3采样时间清空  
ADC1->SMPR2|=7<<9;      //通道3  239.5周期,提高采样时间可以提高精确度  
ADC1->SMPR2|=7<<6;      //通道2  239.5周期,提高采样时间可以提高精确度  
ADC1->SMPR2|=7<<3;      //通道1  239.5周期,提高采样时间可以提高精确度  
ADC1->SMPR2|=7<<0;      //通道0  239.5周期,提高采样时间可以提高精确度  

///5,开启AD转换器,并校准
ADC1->CR2|=1<<0;    //开启AD转换器  
ADC1->CR2|=1<<3;        //使能复位校准   ///1:初始化校准寄存器。
while(ADC1->CR2&1<<3);  //等待校准结束 ///0:校准寄存器已初始化
    //该位由软件设置并由硬件清除。在校准寄存器被初始化后该位将被清除。  
ADC1->CR2|=1<<2;        //开启AD校准   
while(ADC1->CR2&1<<2);  //等待校准结束
//该位由软件设置以开始校准,并在校准结束时由硬件清除  
}

3,中断函数:(主要还是显示)
u16 ADC1_DR, adcx1;
void DMAChannel1_IRQHandler(void)
{       
u16 i;
u32 sum[6]={0}; 
float TEMP; 
LED0 =!LED0;
ADC1->CR2&=~(1<<1);        //关闭连续转换            
for( i = 0; i<768 ;i+= 6)
{
sum[0] += SendBuff;
sum[1] += SendBuff[i+1];
sum[2] += SendBuff[i+2];
sum[3] += SendBuff[i+3];
sum[4] += SendBuff[i+4];
sum[5] += SendBuff[i+5];
}
for(i = 0;i <6 ;i++)
{
ADC1_DR = sum/6;
TEMP=(float)ADC1_DR*(3.3/4096); 
adcx1=TEMP;
LCD_ShowNum(149,70+i*20,adcx1,1,16);//显示电压值
TEMP-=adcx1;
TEMP*=1000;
LCD_ShowNum(165,70+i*20,TEMP,3,16);
}

delay_ms(200); 
DMA1->IFCR |= 1<<1;        //清零通道完成中断标志位
ADC1->CR2|=1<<1;           //启用连续转换            
ADC1->CR2|=1<<22;          //启动规则转换通道          
}

4,main函数的内容:
u8 SendBuff[768];
int main(void)
{
u16 adcx;
float temp;
  Stm32_Clock_Init(9);//系统时钟设置
delay_init(72); //延时初始化
uart_init(72,9600); //串口1初始化   
LED_Init();
LCD_Init();  
Adc_Init();

POINT_COLOR=RED;//设置字体为红色 
LCD_ShowString(60,50,"Mini STM32");
LCD_ShowString(60,70,"ADC TEST");
LCD_ShowString(60,90,"ATOM@ALIENTEK");
LCD_ShowString(60,110,"2010/12/30");
//显示提示信息
POINT_COLOR=BLUE;//设置字体为蓝色
LCD_ShowString(60,130,"ADC_CH0_VAL:");      
LCD_ShowString(60,150,"ADC_CH0_VOL:0.000V");
MYDMA_Config(DMA1_Channel1,(u32)&ADC1->DR,(u32)SendBuff,768);

MYDMA_Enable(DMA1_Channel1);      
while(1)
{
LED0=!LED0;
delay_ms(250);
}
}

    上面就是小弟自己修改的地方,但是在tft屏幕上面,将PA0和3.3v的电压点接触后,数据没有一点反应,上面的中断函数的内容,也是参考了网上的写法,但是主要目的依然是在屏幕上面显示数据的。
    希望各位看官和原子大哥能帮忙分析一下看是什么原因。







正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-6-27 16:39:50 | 显示全部楼层
论坛有人发过ADC,DMA成功的实例.你可以先搜索一下.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

1

主题

22

帖子

0

精华

新手上路

积分
48
金钱
48
注册时间
2013-3-13
在线时间
0 小时
发表于 2013-8-12 18:16:26 | 显示全部楼层
楼主的这个成功了吗?能否将工程共享一下
逝者如斯夫不舍昼夜
回复 支持 反对

使用道具 举报

1

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
51
金钱
51
注册时间
2013-9-3
在线时间
0 小时
发表于 2013-9-8 22:20:35 | 显示全部楼层
回复【楼主位】jiafangshi:
---------------------------------
开启独立工作模式又开启循环扫描模式 这都行啊
回复 支持 反对

使用道具 举报

10

主题

36

帖子

0

精华

初级会员

Rank: 2

积分
106
金钱
106
注册时间
2012-7-7
在线时间
2 小时
发表于 2014-5-29 09:47:10 | 显示全部楼层
你这问题解决了吗,解决了回来填个坑吧
回复 支持 反对

使用道具 举报

39

主题

156

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
417
金钱
417
注册时间
2012-12-23
在线时间
19 小时
发表于 2014-6-3 11:01:13 | 显示全部楼层
ADC1->CR1&=(1<<8);    //扫描模式   
ADC1->CR2&=(1<<1);    //连续转换模式
你确定这样设置可以设置成扫描模式和连续转换?
如果ADC1->CR1的第八位原来是0呢? ADC1->CR2的第一位原来也是0呢?
天道酬勤
回复 支持 反对

使用道具 举报

39

主题

160

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
298
金钱
298
注册时间
2014-1-9
在线时间
8 小时
发表于 2014-6-3 11:58:20 | 显示全部楼层
//******************************************************************
//????????  ADC_GPIO_Config

//??????    2014-03-17
//??????    ??ADC????×?????????IO????????????
//????????????
//·???????  ??
//????????????
//******************************************************************
 void ADC_GPIO_Config(void)
{
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStruct;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 , ENABLE);
       
     GPIO_InitStruct.GPIO_Pin    = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2;
GPIO_InitStruct.GPIO_Mode   = GPIO_Mode_AIN;
GPIO_Init(GPIOC,&GPIO_InitStruct);

    RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //?è??ADC??·????ò×?6, 72M/6=12,ADC??×??ó???ù????????????14M
    ADC_DeInit(ADC1);                   //????ADC1,?? ADC1 ?è???±???è??

ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC???¤×÷???????è???????¤×÷????
ADC_InitStructure.ADC_ScanConvMode = ENABLE;       //ADC?¤×÷???¨?è??????Scan=1
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //ADC?¤×÷??????????
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //×??????í????·?
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC????????????????
ADC_InitStructure.ADC_NbrOfChannel = 3; //???¨????????ADC×?????????
ADC_Init(ADC1, &ADC_InitStructure); //?÷??ADC_InitStruct????????ADCx1??????  

ADC_RegularChannelConfig(ADC1,ADC_Channel_10, 1,ADC_SampleTime_239Cycles5); //?¨??1?????ù,???ù????239.5??????
ADC_RegularChannelConfig(ADC1,ADC_Channel_11, 2,ADC_SampleTime_239Cycles5); //?¨??1?????ù,???ù????239.5??????
      ADC_RegularChannelConfig(ADC1,ADC_Channel_12, 3,ADC_SampleTime_239Cycles5); //?¨??1?????ù,???ù????239.5??????
//????ADC????×?

ADC_DMACmd(ADC1,ENABLE);  //???????¨??ADC??DMA???ó

ADC_Cmd(ADC1, ENABLE); //???????¨??ADC1

ADC_ResetCalibration(ADC1); //??????????×?
 
while(ADC_GetResetCalibrationStatus(ADC1)); //??????????×??á??

ADC_StartCalibration(ADC1);  //????ADC????×?
 
while(ADC_GetCalibrationStatus(ADC1));  //??????×??á??
 
//ADC_SoftwareStartConvCmd(ADC1,ENABLE); //???????¨??ADC1??×???????

}
//******************************************************************
//????????  ADC_DMA_Config

//??????    2014-03-17
//??????    ???±??????±????±??
//???????????????????±??
//·???????  ??
//????????????
//******************************************************************
void ADC_DMA_Config(void)
{


 DMA_InitTypeDef DMA_InitStructure;
   RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //????DMA1????
  __nop();                    //???? DMA1 ?±?????¨,DMA?????è???±?????¨
   __nop();                    //??????×??? 2 ?? nop
   __nop();

    DMA_DeInit(DMA1_Channel1);   //??DMA???¨??1?????÷???è???±????
 

// DMA1_MEM_LEN=cndtr;
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)ADC1_DR_Address;  //
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADC_Keep;  //
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;  //
DMA_InitStructure.DMA_BufferSize = N*M;  //
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  //
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  //
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;  //
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;  //
DMA_InitStructure.DMA_Priority = DMA_Priority_High; //
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  //
DMA_Init(DMA1_Channel1, &DMA_InitStructure);  //

//DMA_Cmd(DMA1_Channel1, ENABLE);  //
  

这是我的,反正我用的没问题
回复 支持 反对

使用道具 举报

39

主题

160

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
298
金钱
298
注册时间
2014-1-9
在线时间
8 小时
发表于 2014-6-3 11:58:57 | 显示全部楼层
额,怎么注释都变成这个了?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-7-7 13:55

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表