2025年玩转TM4C1294XL(7)——ADC+uDMA+Timer触发配置(uDMA ping-pong模式)

玩转TM4C1294XL(7)——ADC+uDMA+Timer触发配置(uDMA ping-pong模式)1 简介 简单介绍芯片内部的 ADC 和 uDMA 模块 分享 ADC uDMA Timer 触发配置 本人是边学习边记录 内容仅作参考 有错误的地方请见谅 2 ADC 介绍 本部分内容参考自 TI 官方手册 芯片内部的 ADC 模块具有两路 ADC 分别为 ADC0 和 ADC1 共享 20 个输入通道

大家好,我是讯享网,很高兴认识大家。

1.简介
       简单介绍芯片内部的ADC和uDMA模块,分享ADC+uDMA+Timer触发配置。本人是边学习边记录,内容仅作参考,有错误的地方请见谅。

2.ADC介绍
       本部分内容参考自TI官方手册。
       芯片内部的ADC模块具有两路ADC,分别为ADC0和ADC1,共享20个输入通道,最大采样速度2M(两个ADC交替采样最大可以达到4M),可以配置成4个采样队列,支持软件触发、定时器触发、pwm触发、比较器触发、io口触发,支持硬件平均(最多64次采样),8个数字比较器,参考电压可选择。
在这里插入图片描述
讯享网

图1 ADC模块功能框图

       
       需要注意的是4个队列的长度不一样,队列0最多支持8个通道,队列1和2支持4个通道,队列3只支持1个通道。
在这里插入图片描述

图2 ADC的队列长度表

       
3.uDMA介绍
       本部分内容参考自TI官方手册。
       芯片内部的uDMA模块具有32个独立通道,支持内存到内存、内存到外设、外设到内存三个传输方向,支持多种传输模式,支持8位、16位、32位数据宽度,一次可传输的数据长度最大1024,源地址和目标地址自增可控。uDMA的通道配置参数存储在用户提供的RAM中,需要在程序中定义一个长度为1024字节的数组用于存放通道配置参数,这个数组需要以1024字节进行地址对齐。
在这里插入图片描述

图3 uDMA控制参数结构表

4.配置代码
       本部分代码实现timer触发ADC转换使用uDMA搬运,uDMA工作在ping-pong模式下。

 enum BUFFER_STATUS { 
    EMPTY, FILLING, FULL }; //dma控制块需要1024字节对齐 static uint8_t ControlTable[1024] __attribute__ ((aligned(1024))); uint16_t ADCBuffer1[ADC_SAMPLE_BUF_SIZE]; uint16_t ADCBuffer2[ADC_SAMPLE_BUF_SIZE]; static enum BUFFER_STATUS BufferStatus[2]; //ADC队列0中断函数 uint32_t adc_int_count = 0; //记录中断次数 void ADC0SS0_Handler(void) { 
    adc_int_count++; HWREG(ADC0_BASE + ADC_O_ISC) = HWREG(ADC0_BASE + ADC_O_RIS) & (1 << 8); //清中断 //判断哪个buffer满了,进行切换 if ((uDMAChannelModeGet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT) == UDMA_MODE_STOP) && (BufferStatus[0] == FILLING)) { 
    BufferStatus[0] = FULL; BufferStatus[1] = FILLING; } else if ((uDMAChannelModeGet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT) == UDMA_MODE_STOP) && (BufferStatus[1] == FILLING)) { 
    BufferStatus[0] = FILLING; BufferStatus[1] = FULL; } if(BufferStatus[0] == FULL) { 
    BufferStatus[0] = EMPTY; //使能另一个传输块 uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO0), ADCBuffer1, ADC_SAMPLE_BUF_SIZE); //启动DMA通道 uDMAChannelEnable(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT); } else if(BufferStatus[1] == FULL) { 
    BufferStatus[1] = EMPTY; uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO0), ADCBuffer2, ADC_SAMPLE_BUF_SIZE); uDMAChannelEnable(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT); } } void bsp_InitAdc0(void) { 
    BufferStatus[0] = FILLING; BufferStatus[1] = EMPTY; //使能外设时钟 SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA); SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); //GPIO配置 GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3); uDMAEnable(); uDMAControlBaseSet(ControlTable); //设置控制块 //清除通道属性 uDMAChannelAttributeDisable(UDMA_CHANNEL_ADC0, UDMA_ATTR_ALTSELECT | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK); //配置主控制块参数,16位数据宽度、源地址不自增、目标地址16bit自增、每次都触发。 uDMAChannelControlSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1); //配置副控制块参数,16位数据宽度、源地址不自增、目标地址16bit自增、每次都触发。 uDMAChannelControlSet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1); //主控制块发送设置,ping-pong模式、源地址(void *)(ADC0_BASE + ADC_O_SSFIFO0)、 //目标地址ADCBuffer1、传输大小ADC_SAMPLE_BUF_SIZE uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO0), ADCBuffer1, ADC_SAMPLE_BUF_SIZE); //副控制块发送设置,ping-pong模式、源地址(void *)(ADC0_BASE + ADC_O_SSFIFO0)、 //目标地址ADCBuffer2、传输大小ADC_SAMPLE_BUF_SIZE uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO0), ADCBuffer2, ADC_SAMPLE_BUF_SIZE); //设置连续传输 uDMAChannelAttributeEnable(UDMA_CHANNEL_ADC0, UDMA_ATTR_USEBURST); //开启DMA通道 uDMAChannelEnable(UDMA_CHANNEL_ADC0); // ADC0时钟配置 全速1M PIOSC为16M时钟 ADCClockConfigSet(ADC0_BASE, ADC_CLOCK_SRC_PIOSC | ADC_CLOCK_RATE_FULL, 1); //等待时钟配置 SysCtlDelay(10); //关闭队列0中断 IntDisable(INT_ADC0SS0); ADCIntDisable(ADC0_BASE, 0); //关闭队列0 ADCSequenceDisable(ADC0_BASE, 0); ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_TIMER, 0); //定时器触发 // ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_ALWAYS, 0); //连续不断采样 全速 //队列0,编号0,通道ch0|最后一个采样通道 ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_CH0 | ADC_CTL_END); //使能队列0 ADCSequenceEnable(ADC0_BASE, 0); //使能队列0的dma ADCSequenceDMAEnable(ADC0_BASE, 0); //开启队列0的dma传输完成中断 ADCIntEnableEx(ADC0_BASE, ADC_INT_DMA_SS0); //开启队列0中断控制器 IntEnable(INT_ADC0SS0); //使能处理器中断控制器 IntMasterEnable(); //定时器配置 TimerConfigure(TIMER0_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PERIODIC); //16k频率 TimerLoadSet(TIMER0_BASE, TIMER_A, (SystemCoreClock/16000) - 1); //使能定时器A触发 TimerControlTrigger(TIMER0_BASE, TIMER_A, true); //使能定时器 TimerEnable(TIMER0_BASE, TIMER_A); } 

讯享网

       ADC0队列0转换完成后dma自动将数据放入缓存中,ping-pong模式使用了双缓冲,dma传输完成后会进入ADC0SS0_Handler中断函数,函数中切换缓存然后重新启动传输。

keil工程下载

小讯
上一篇 2025-03-08 10:46
下一篇 2025-03-06 18:56

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/36350.html