1.简介
简单介绍芯片内部的ADC和uDMA模块,分享ADC+uDMA+Timer触发配置。本人是边学习边记录,内容仅作参考,有错误的地方请见谅。
2.ADC介绍
本部分内容参考自TI官方手册。
芯片内部的ADC模块具有两路ADC,分别为ADC0和ADC1,共享20个输入通道,最大采样速度2M(两个ADC交替采样最大可以达到4M),可以配置成4个采样队列,支持软件触发、定时器触发、pwm触发、比较器触发、io口触发,支持硬件平均(最多64次采样),8个数字比较器,参考电压可选择。

讯享网
需要注意的是4个队列的长度不一样,队列0最多支持8个通道,队列1和2支持4个通道,队列3只支持1个通道。

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


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