应用还可以结合外部触发功能与DMA传输功能,实现TIM触发多通道 ADC 转换,DMA装载数据的功能。
具体可以参考官方的Lib样例程序:
http://www.mindmotion.com.cn/getfile.aspx?id=1219
下面通过寄存器配置多个通道,实现多路转换,多次切换任意通道,附上全部Reg版本Demo代码:
// Define to prevent recursive inclusion
#define _ADC_C_
// Files includes
#include "delay.h"
#include "sys.h"
#include "uart.h"
#include "adc.h"
#define ADCSCANNUM 4
#define RESULTLEN 4
vu8 ADCflag = 0;
u16 ADC_flag;
u16 ADCValue[ADCSCANNUM];
u16 varADC_ResultList[RESULTLEN+10][ADCSCANNUM];
void ADC_AnyChanChangeDefault(void)
{
MODIFY_REG(ADC1->CHANY0,ADC1_CHANY0_SEL0, 0<
MODIFY_REG(ADC1->CHANY0,ADC1_CHANY0_SEL1, 2<
MODIFY_REG(ADC1->CHANY0,ADC1_CHANY0_SEL2, 5<
MODIFY_REG(ADC1->CHANY0,ADC1_CHANY0_SEL3, 7<
}
void ADC1_AnyChanMultiChannelInit(void)
{
SET_BIT(RCC->AHBENR,RCC_AHBENR_GPIOA); //enable GPIOA clock
SET_BIT(RCC->APB2ENR, RCC_APB2ENR_ADC1EN); //enable ADC1clock
//set PA0,2,5,7 as Analog Input
MODIFY_REG(GPIOA->CRL, (GPIO_CNF_MODE_MASK << GPIO_CRL_CNF_MODE_0_Pos), GPIO_CNF_MODE_AIN << GPIO_CRL_CNF_MODE_0_Pos);
MODIFY_REG(GPIOA->CRL, (GPIO_CNF_MODE_MASK << GPIO_CRL_CNF_MODE_2_Pos), GPIO_CNF_MODE_AIN << GPIO_CRL_CNF_MODE_2_Pos);
MODIFY_REG(GPIOA->CRL, (GPIO_CNF_MODE_MASK << GPIO_CRL_CNF_MODE_5_Pos), GPIO_CNF_MODE_AIN << GPIO_CRL_CNF_MODE_5_Pos);
MODIFY_REG(GPIOA->CRL, (GPIO_CNF_MODE_MASK << GPIO_CRL_CNF_MODE_7_Pos), GPIO_CNF_MODE_AIN << GPIO_CRL_CNF_MODE_7_Pos);
SET_BIT(RCC->APB2RSTR,RCC_APB2RSTR_ADC1RST); //ADC1reset
CLEAR_BIT(RCC->APB2RSTR,(RCC_APB2RSTR_ADC1RST)); //reset end
//ADC configure soft trigger, single period mode
//8 fractional frequency
MODIFY_REG(ADC1->ADCFG, ADC_CFGR_PRE, ADCFG_ADCPRE_8);
MODIFY_REG(ADC1->ADCR,
ADCR_ADMD_PERIOD | ADCR_ADMD_CONTINUE | ADCR_ALIGN_LEFT,
ADCR_ADMD_PERIOD);
SET_BIT(ADC1->ADCHS, ADCHS_CHEN0|ADCHS_CHEN2|ADCHS_CHEN5|ADCHS_CHEN7);
//single PERIOD mode , Data right-ALIGNED, discontinue
//enable 4 channels
WRITE_REG(ADC1->ANYCFG, 4);
//Enable chan 0,2,5, 7
ADC_AnyChanChangeDefault();
SET_BIT(ADC1->ADCR, ADC_CR_DMAEN);
SET_BIT(ADC1->ADCFG,ADCFG_ADEN);//ADC1 enable
}
void ADC_AnyChanChangeFirst(void)
{
MODIFY_REG(ADC1->CHANY0,ADC1_CHANY0_SEL0, 2<
MODIFY_REG(ADC1->CHANY0,ADC1_CHANY0_SEL1, 0<
MODIFY_REG(ADC1->CHANY0,ADC1_CHANY0_SEL2, 5<
MODIFY_REG(ADC1->CHANY0,ADC1_CHANY0_SEL3, 7<
}
void ADC_AnyChanChangeSecond(void)
{
MODIFY_REG(ADC1->CHANY0,ADC1_CHANY0_SEL0, 5<
MODIFY_REG(ADC1->CHANY0,ADC1_CHANY0_SEL1, 0<
MODIFY_REG(ADC1->CHANY0,ADC1_CHANY0_SEL2, 2<
MODIFY_REG(ADC1->CHANY0,ADC1_CHANY0_SEL3, 7<
}
void ADC_AnyChanChangeThird(void)
{
MODIFY_REG(ADC1->CHANY0,ADC1_CHANY0_SEL0, 0<
MODIFY_REG(ADC1->CHANY0,ADC1_CHANY0_SEL1, 7<
MODIFY_REG(ADC1->CHANY0,ADC1_CHANY0_SEL2, 5<
MODIFY_REG(ADC1->CHANY0,ADC1_CHANY0_SEL3, 2<
}
void M0_NVIC_Init(u32 NVIC_IRQChannelPriority, IRQn_Type NVIC_IRQChannel, FunctionalState NVIC_IRQChannelCmd)
{
if (NVIC_IRQChannelCmd != DISABLE)
{
NVIC->IP[NVIC_IRQChannel >> 0x02] =
(NVIC->IP[NVIC_IRQChannel >> 0x02] &
(~(((u32)0xFF) << ((NVIC_IRQChannel & 0x03) * 8)))) |
((((u32)NVIC_IRQChannelPriority << 6) & 0xFF) << ((NVIC_IRQChannel & 0x03) * 8));
NVIC->ISER[0] = 0x01 << (NVIC_IRQChannel & 0x1F);
}
else
{
NVIC->ICER[0] = 0x01 << (NVIC_IRQChannel & 0x1F);
}
}
void DMA1_Channel1_IRQHandler()
{
if(DMA1->ISR & DMA_ISR_TCIF1)
{
DMA1->IFCR = DMA_IFCR_CTCIF1;
ADCflag = 1;
}
}
void DMAcheckStatus(u32 DMA_FLAG)
{
while(1)
{
if(DMA1->ISR & DMA_FLAG)
{
DMA1->IFCR = DMA_FLAG;
break;
}
}
}
void DMAdisable(DMA_Channel_TypeDef* DMAy_Channelx)
{
//disable DMA_EN
DMAy_Channelx->CCR &= 0xFFFFFFFE;
}
void DMA_AdctoM16_Init(void)
{
DMA_Channel_TypeDef* dma_channel;
dma_channel = DMA1_Channel1;
RCC->AHBENR |= RCC_AHBENR_DMA1EN ;
DELAY_Ms(5); //wait DMAclock stabilization
DMAdisable(dma_channel);
dma_channel->CPAR = (u32) & (ADC1->DR);; //DMA1 external address
dma_channel->CMAR = (u32)ADCValue; //DMA1,memory device address
dma_channel->CCR &= ~DMA_CCR1_DIR;
dma_channel->CNDTR = ADCSCANNUM;
dma_channel->CCR &= ~DMA_CCR1_PINC;
dma_channel->CCR |= DMA_CCR1_MINC;
dma_channel->CCR |= DMA_CCR1_PSIZE_0; //external data 16bit
dma_channel->CCR |= DMA_CCR1_MSIZE_0; //memory device data 16bit
dma_channel->CCR |= DMA_CCR1_PL_0; //Medium priority
dma_channel->CCR |= DMA_CCR_CIRC;
dma_channel->CCR &= ~DMA_CCR1_MEM2MEM; //register memory device to memory device mode
M0_NVIC_Init(0, DMA1_Channel1_IRQn, ENABLE);
dma_channel->CCR |= DMA_CCR1_TCIE;
ADCflag = 0x0;
dma_channel->CCR |= DMA_CCR1_EN; //start DMA transmission
}
void Get_ResultListFun(u16 list_number)
{
u16 chan = 0;
for(chan = 0; chan < ADCSCANNUM; chan++)
{
varADC_ResultList[list_number][chan] = ADCValue[chan];
}
}
void ADC_ConvertSoftwareStart(ADC_TypeDef* adc, FunctionalState state)
{
(state) ? (adc->ADCR |= ADC_CR_ADST) : (adc->ADCR &= ~ADC_CR_ADST);
}
u16 ADC1_MultiChanAnyDemo(void)
{
ADC1_AnyChanMultiChannelInit();
DMA_AdctoM16_Init();
ADC_ConvertSoftwareStart(ADC1, ENABLE);
ADCflag = 0;
while(1)
{
if(ADCflag == 1)
{
ADCflag = 0;
Get_ResultListFun(0);
break;
}
}
ADC_AnyChanChangeFirst();
ADC_ConvertSoftwareStart(ADC1, ENABLE);
while(1)
{
if(ADCflag == 1)
{
ADCflag = 0;
Get_ResultListFun(1);
break;
}
}
ADC_AnyChanChangeSecond();
ADC_ConvertSoftwareStart(ADC1, ENABLE);
while(1)
{
if(ADCflag == 1)
{
ADCflag = 0;
Get_ResultListFun(2);
break;
}
}
ADC_AnyChanChangeThird();
ADC_ConvertSoftwareStart(ADC1, ENABLE);
while(1)
{
if(ADCflag == 1)
{
ADCflag = 0;
Get_ResultListFun(3);
break;
}
}
return 0;
}
0