IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 玩转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个输入通道,最大采样速度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工程下载

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-04-06 23:22:24  更:2022-04-06 23:23:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 4:35:24-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码