参考论坛
@linshisong 大神的程序写的寄存器版本,因为自己需要用到ADC+DMA,而且这个也研究了挺久的。
先说一下我遇到的问题:
1.我是在原来自己写的代码的基础上改的,然后ADC没有设置成连续转换模式,需要开启连续转换模式ADC才会连续不断的给DMA发送启动信号,
不然就要在循环里面一直等待AD转换完成然后开启下一次转换。
2.DMA如果没有设置成循环模式,就需要在DMA的中断里面不断重装缓存值(DMA1_Channel1->CNDTR)。
3.外设地址的写法:(u32)(&ADC1->DR)。
希望可以帮到大家,因为一直都是伸手党,现在也来贡献一下。
[mw_shl_code=applescript,true]#include "adc.h"
#include "stm32f10x.h" // Device header
#include "usart.h"
#include "led.h"
extern volatile u16 SendBuff[SEND_BUF_SIZE];//AD转换保存的数据
void adc1_in1_init(void)
{
RCC->APB2ENR |= 1<<2;//开启PA口时钟
RCC->APB2ENR |= 1<<9;//开启ADC1时钟
/*修改*/
GPIOA->CRL &= ~(0xFF<<(1*4));//PA1口配置为模拟输入
RCC->CFGR &= ~(3<<14);
RCC->CFGR |= (2<<14);//选择6分频,72/6=12MHz
RCC->APB2RSTR |= (1<<9);//复位ADC1模块
RCC->APB2RSTR &= ~(1<<9);//复位完成
ADC1->CR1 &= ~(1<<23); //在规则通道上禁用模拟看门狗
ADC1->CR1 &= ~(1<<22); //在注入通道上禁用模拟看门狗
ADC1->CR1 &= ~(0xF<<16); //独立模式
ADC1->CR2 |= 1<<20;//开启规则通道外部触发
ADC1->CR2 |= 7<<17;//规则通道可以通过SWSTART来开启转换
ADC1->CR2 &= ~(1<<15);//不开启注入通道外部触发
ADC1->CR2 &= ~(1<<11);//数据右对齐
ADC1->CR2 |= 1<<1; //ADC工作在连续模式
/*修改*/
ADC1->SMPR2 &= ~(0x7<<3);
ADC1->SMPR2 |= (0x7<<3);//设置通道1采样时间为239.5个周期
ADC1->SQR1 &= ~(0xF<<20);//设置规则组的有一个通道转换
/*修改*/
ADC1->SQR3 &= ~(0x1F<<(0*5));
ADC1->SQR3 |= 0x1<<(0*5);//通道1第一个转换
ADC1->CR2 |= 0x1<<8; //使用DMA模式
ADC1->CR2 |= 1<<0; //ADC1进入断电模式,等待唤醒
delay_us(10);
ADC1->CR2 |= 1<<3; //初始化校准寄存器
while(ADC1->CR2 & (1<<3));//等待校准寄存器初始化完成
ADC1->CR2 |= 1<<2; //开始校准
while(ADC1->CR2 & (1<<2));//等待校准完成
ADC1->CR2 |= 1<<22; //开启ADC并开始转换
}
/*****************************************
函数:MYDMA1_CH1_Config(u32 src_addr,u32 target_addr,u16 transfer_num)
功能:
DMA1的通道1配置
这里的传输形式是固定的,这点要根据不同的情况来修改
从存储器->外设模式/16位数据宽度/存储器增量模式
参数:
src_addr:外设地址
target_addr:存储器地址
返回值:无
*****************************************/
void MYDMA1_CH1_Config(u32 src_addr,u32 target_addr)
{
u32 priority;
RCC->AHBENR|=1<<0; //开启DMA1时钟
delay_ms(5); //等待DMA时钟稳定
DMA1_Channel1->CCR &= ~(1<<0); //先关闭DMA1通道1
//生成一个优先级编码,组2,抢占优先级2个位(范围0~3),响应优先级2(范围0~3)
priority=NVIC_EncodePriority (7-2,1,2);
//设置优先级
NVIC_SetPriority(DMA1_Channel1_IRQn,priority);
//使能DMA1中断
NVIC_EnableIRQ(DMA1_Channel1_IRQn);
DMA1_Channel1->CCR &= ~(1<<4); //从外设读
DMA1_Channel1->CCR |= (1<<5); //工作在循环模式
DMA1_Channel1->CCR &= ~(1<<6); //外设地址不增
DMA1_Channel1->CCR |= 1<<7; //存储器地址增
DMA1_Channel1->CCR |= 1<<10; //数据宽度为16位,adc的精度为12位
DMA1_Channel1->CCR |= 1<<12; //通道优先级为中
DMA1_Channel1->CCR &= ~(1<<14); //非存储器到存储器模式
DMA1_Channel1->CNDTR=50;//DMA传输数量
DMA1_Channel1->CMAR=target_addr; //存储器地址送入寄存器
DMA1_Channel1->CPAR=src_addr; //外设地址送入寄存器
DMA1->IFCR &= ~(1<<0); //清除全局中断标志
DMA1_Channel1->CCR &= ~(1 << 3); //禁止传输错误中断
DMA1_Channel1->CCR &= ~(1 << 2); //禁止半传输中断
DMA1_Channel1->CCR |= 1<<1; //使能传输完成中断
DMA1_Channel1->CCR |= 1<<0; //开启DMA传输
}
/*****************************************
函数:adc1_get
功能:单次转换AD
参数:无
返回值:转换后的数字量
*****************************************/
u16 adc1_get(void)
{
ADC1->CR2 |= 1<<22;
while(!(ADC1->SR & (1<<1)));//等待转换完成
return ADC1->DR;
}
/*****************************************
函数:adc1_getnum
功能:多次转换AD
参数:num:转换的次数
返回值:转换后的数字量
*****************************************/
u16 adc1_getnum(u8 num)
{
u32 times=0;
u16 sum=0;
for(times=0;times<num;times++)
sum+=adc1_get();
return sum/times;
}
/*****************************************
函数:DMA1_Channel1_IRQHandler
功能:dma1通道1中断服务函数
参数:none
返回值:none
*****************************************/
void DMA1_Channel1_IRQHandler()
{
LED2=!LED2;
if(DMA1->ISR & (1<<1))
{
char i=50;
for(i=0;i<50;i++)
printf("%d
",SendBuff
);
DMA1->IFCR= ~(1<<1); //清除中断标志位
/*如果DMA工作在循环模式则不需要下面这三行代码*/
// DMA1_Channel1->CCR &= ~(1<<0); //先关闭DMA1通道1
// DMA1_Channel1->CNDTR=50;//DMA传输数量
// DMA1_Channel1->CCR |= 1<<0; //开启DMA传输
}
printf("jinzhongduan
");
}
[/mw_shl_code]
ADC DMA(寄存器版).zip
(895.53 KB, 下载次数: 135)
2017-2-22 16:03 上传
点击文件名下载附件
一周热门 更多>