adc和dma的例程
请问有没有adc多通道采样dma的例程?官方的例程太少了啊。好像只有单通道ADC加DMA的例程,不过这个只需要在单通道例程上修改一下即可 adc多通道采集可以不采用dma。 网上有很多ADC与DMA结合的例程 adc+dma传输 传输完成标志得不到 DMA会自动递增地址存放数据,递增设置的长度之后会自动复位地址重新开始从第一个地址写数据,覆盖掉之前的数据。 ADC连续扫描模式必须要用DMA吗 ADC DMA多通道采集到的数据相互有干扰,该怎么破? 我是用于对两个2Hz的波形采样其中的40ms片段;两通道采样,40ms采样100~200次,用DMA比较方便,当然也可以不用DMA。
谁知N32L40x系列的DMA搬运ADC数据有bug。最后放弃使用DMA了。
以下是ADC两通道采样+DMA的测试代码,供参考吧。
MCU为N32L403KB,时钟AHB=APB1=APB2=HSI 16M。
#define AD_NUM 200
staticu16 ADCConvertedValue={0};
//DMA初始化
void DMA_sl_Init(void)
{
DMA_InitTypeDMA_InitStructure;
DMA_DeInit(DMA_CH1);
RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_DMA, ENABLE);
DMA_InitStructure.PeriphAddr = (u32)&ADC->DAT;
DMA_InitStructure.MemAddr = (u32)ADCConvertedValue;
DMA_InitStructure.Direction = DMA_DIR_PERIPH_SRC;
DMA_InitStructure.BufSize = AD_NUM; //非循环模式时,DMA接收够Size后,CHEN位=0,DMA停止
DMA_InitStructure.PeriphInc = DMA_PERIPH_INC_DISABLE;
DMA_InitStructure.DMA_MemoryInc= DMA_MEM_INC_ENABLE;
DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_SIZE_HALFWORD;
DMA_InitStructure.MemDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.CircularMode = DMA_MODE_NORMAL; //DMA循环模式和ADC连续转换,可有4种组合
DMA_InitStructure.Priority = DMA_PRIORITY_HIGH;
DMA_InitStructure.Mem2Mem = DMA_M2M_DISABLE;
DMA_Init(DMA_CH1, &DMA_InitStructure);
DMA_RequestRemap(DMA_REMAP_ADC1, DMA, DMA_CH1, ENABLE);
DMA_EnableChannel(DMA_CH1, ENABLE);
}
//ADC多通道+DMA
void ADC_DMA_Sample(void)
{
ADC_InitTypeADC_InitStructure;
GPIO_InitType GPIO_InitStructure;
//GPIO配置,两通道模拟输入
GPIO_InitStruct(&GPIO_InitStructure);
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE);
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE);
GPIO_InitStructure.Pin = GPIO_PIN_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Analog;
GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIO_PIN_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Analog;
GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
//DMA配置
DMA_sl_Init();
//ADC最好先Deinit再配置
ADC_DeInit(ADC);
RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_ADC, ENABLE);
ADC_ConfigClk(ADC_CTRL3_CKMOD_AHB, RCC_ADCHCLK_DIV16); //ADC时钟: AHB/16=16M/16=1M
RCC_ConfigAdc1mClk(RCC_ADC1MCLK_SRC_HSI, RCC_ADC1MCLK_DIV16);//ADC1M: HSI=16M, 16M/16=1M
//ADC配置
ADC_InitStructure.MultiChEn = ENABLE;
ADC_InitStructure.ContinueConvEn = ENABLE; //ADC连续转换和DMA循环模式,可有4种组合
ADC_InitStructure.ExtTrigSelect= ADC_EXT_TRIGCONV_NONE;
ADC_InitStructure.DatAlign = ADC_DAT_ALIGN_R;
ADC_InitStructure.ChsNumber = 2;
ADC_Init(ADC, &ADC_InitStructure);
//ADC通道序列配置
ADC_ConfigRegularChannel(ADC, ADC_CH_1_PA0,1, ADC_SAMP_TIME_239CYCLES5); //239.5+12.5=252个时钟=252us,1ms采4次
ADC_ConfigRegularChannel(ADC, ADC_CH_10_PB1, 2, ADC_SAMP_TIME_239CYCLES5);
//ADC使能
ADC_EnableDMA(ADC, ENABLE);
ADC_Enable(ADC, ENABLE);
while(ADC_GetFlagStatusNew(ADC,ADC_FLAG_RDY) == RESET);
//ADC校准
ADC_StartCalibration(ADC);
while (ADC_GetCalibrationStatus(ADC));
//启动ADC
ADC_EnableSoftwareStartConv(ADC, ENABLE);
//用于测试DMA循环模式和ADC连续转换的4种组合
while(1)
{
//DMA普通模式和循环模式的CHEN
if ((DMA_CH1->CHCFG & DMA_CHCFG1_CHEN) == 0)
{
//DMA停止后需要重新进行配置
DMA_sl_Init();
ADC_EnableSoftwareStartConv(ADC, ENABLE);
}
//ADC连续转换和单次转换的ENDC
if (ADC_GetFlagStatus(ADC, ADC_FLAG_ENDC) != 0)
{
ADC_EnableSoftwareStartConv(ADC, ENABLE);
}
};
}
N32L40x系列的DMA搬运ADC数据有bug?能说一下是什么bug吗?
我用的是N32L406CB,使用DMA后,波特率太高的话,很容易卡死,复位也没用,只能断电重启才行,不知道是代码的问题,还是什么原因 qinlicn 发表于 2022-11-2 10:21
我是用于对两个2Hz的波形采样其中的40ms片段;两通道采样,40ms采样100~200次,用DMA比较方便,当然也可以 ...
HSI是8M吧 bitterheart 发表于 2022-11-21 18:37
N32L40x系列的DMA搬运ADC数据有bug?能说一下是什么bug吗?
我用的是N32L406CB,使用DMA后,波特率太高的话 ...
代码贴出来看看 感觉多通道ADC+DMA就容易出现错位的情况 本帖最后由 bitterheart 于 2022-11-23 10:21 编辑
sy12138 发表于 2022-11-22 09:43
代码贴出来看看
DMA配置
RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_DMA, ENABLE);
DMA_DeInit(DMA_CH7);
DMA_StructInit(&DMA_InitStructure);
DMA_InitStructure.PeriphAddr = (uint32_t)(USART2_BASE + 0x04);
// DMA_InitStructure.MemAddr = (uint32_t)TxBuffer1;
DMA_InitStructure.Direction = DMA_DIR_PERIPH_DST;
// DMA_InitStructure.BufSize = TxBufferSize1;
DMA_InitStructure.PeriphInc = DMA_PERIPH_INC_DISABLE;
DMA_InitStructure.DMA_MemoryInc= DMA_MEM_INC_ENABLE;
DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_SIZE_BYTE;
DMA_InitStructure.MemDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.CircularMode = DMA_MODE_NORMAL;
DMA_InitStructure.Priority = DMA_PRIORITY_HIGH;
DMA_InitStructure.Mem2Mem = DMA_M2M_DISABLE;
DMA_Init(DMA_CH7, &DMA_InitStructure);
DMA_RequestRemap(DMA_REMAP_USART2_TX, DMA, DMA_CH7, ENABLE); void UART_DMA_Send(uint8 *pbuf, uint16 len)
{
int len1;
if (len == 0) {
return ;
}
pbuf = '\r';
pbuf = '\n';
if (buf_sel == 0) {
p_wr = print_buf_dma;
} else {
p_wr = print_buf_dma_bk;
}
len1 = print_buf_wrcnt + len;
if (len1 > DMA_PRINTBUF_LEN) {
memcpy(&p_wr, pbuf, DMA_PRINTBUF_LEN-print_buf_wrcnt);
len1 = DMA_PRINTBUF_LEN;
dma_print_err_cnt++;
} else {
memcpy(&p_wr, pbuf, len);
}
print_buf_wrcnt = len1;
dma_wait_cnt = 0;
if (print_dma_wait) {
while (DMA_GetFlagStatus(DMA_FLAG_TC7, DMA) == RESET) {
dma_wait_cnt++;
if (dma_wait_cnt >= DMA_WAIT_TIMEOUT) {
return;
}
}
}
DMA_ClearFlag(DMA_FLAG_TC7, DMA);
print_dma_wait = 1;
buf_sel = (buf_sel + 1) & 1;
print_buf_wrcnt = 0;
DMA_InitStructure.MemAddr = (uint32_t)p_wr;
DMA_InitStructure.BufSize = len1;
DMA_Init(DMA_CH7, &DMA_InitStructure);
DMA_RequestRemap(DMA_REMAP_USART2_TX, DMA, DMA_CH7, ENABLE);
USART_EnableDMA(USART2, USART_DMAREQ_TX, ENABLE);
DMA_EnableChannel(DMA_CH7, ENABLE);
}
void print_dma_flush(void)
{
dma_wait_cnt = 0;
if (print_buf_wrcnt > 0) {
while (DMA_GetFlagStatus(DMA_FLAG_TC7, DMA) == RESET) {
dma_wait_cnt++;
if (dma_wait_cnt >= 100000) { // DMA_WAIT_TIMEOUT) {
// dma_print_err_cnt++;
// break;
}
}
DMA_ClearFlag(DMA_FLAG_TC7, DMA);
print_dma_wait = 1;
DMA_InitStructure.MemAddr = (uint32_t)p_wr;
DMA_InitStructure.BufSize = print_buf_wrcnt;
DMA_Init(DMA_CH7, &DMA_InitStructure);
DMA_RequestRemap(DMA_REMAP_USART2_TX, DMA, DMA_CH7, ENABLE);
USART_EnableDMA(USART2, USART_DMAREQ_TX, ENABLE);
DMA_EnableChannel(DMA_CH7, ENABLE);
// dma_print_err_cnt++;
}
// if (print_dma_wait) {
while (DMA_GetFlagStatus(DMA_FLAG_TC7, DMA) == RESET) {
dma_wait_cnt++;
if (dma_wait_cnt >= 100000) { // DMA_WAIT_TIMEOUT) {
// dma_print_err_cnt++;
// break;
}
}
DMA_ClearFlag(DMA_FLAG_TC7, DMA);
// }
print_dma_wait = 0;
print_buf_wrcnt = 0;
buf_sel = 0;
}
页:
[1]