历史上的今天
返回首页

历史上的今天

今天是:2024年09月11日(星期三)

正在发生

2018年09月11日 | STM32F0 定时器触发ADC,多通道采样、DMA传输数据的配置

2018-09-11 来源:eefocus

本块代码实现了定时器定时触发ADC,多通道采样,并通过DMA进行数据传输到内存的操作。

#include    "adc.h"  

[cpp] view plain copy

#define DMA_BUFFER_SIZE     6  

uint8 sample_finish = 0;  

int16 adc_dma_tab[6] = { 0 };  

uint8 sample_index = 0;  

  

//采样点数据  

int16 sample_1[128] = { 0 };  

int16 sample_2[128] = { 0 };  

int16 sample_3[128] = { 0 };  

int16 sample_4[128] = { 0 };  

int16 sample_5[128] = { 0 };  

int16 sample_6[128] = { 0 };  

  

void user_adc_init()  

{  

    adc_gpio_init();  

    adc_config();               // 注意此处的初始化顺序,否则采样传输的数据容易出现数据错位的结果  

    adc_dma_init();             //  

    adc_timer_init();           //  

  

}  

  

void adc_config()  

{  

    ADC_InitTypeDef adc_init_structure;  

  

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);            //使能ADC时钟  

  

    ADC_DeInit(ADC1);                                               //复位ADC  

    ADC_StructInit(&adc_init_structure);                            //初始化ADC结构体  

  

    adc_init_structure.ADC_ContinuousConvMode = DISABLE;            //禁用连续转换模式  

    adc_init_structure.ADC_DataAlign = ADC_DataAlign_Right;         //采样数据右对齐  

    adc_init_structure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_TRGO; //外部触发设置为TIM2  

    adc_init_structure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;//上升沿触发  

    adc_init_structure.ADC_Resolution = ADC_Resolution_12b;         //12位分辨率  

    adc_init_structure.ADC_ScanDirection = ADC_ScanDirection_Upward;//向上扫描0-18通道  

    ADC_Init(ADC1, &adc_init_structure);  

  

    ADC_OverrunModeCmd(ADC1, ENABLE);                               //使能数据覆盖模式  

    ADC_ChannelConfig(ADC1, ADC_Channel_0 | ADC_Channel_1 | ADC_Channel_2  

                          | ADC_Channel_8 | ADC_Channel_14 | ADC_Channel_15,  

                          ADC_SampleTime_13_5Cycles);               //配置采样通道,采样时间125nS  

    ADC_GetCalibrationFactor(ADC1);                                 //使能前校准ADC  

    ADC_Cmd(ADC1, ENABLE);                                          //使能ADC1  

    while(ADC_GetFlagStatus(ADC1, ADC_FLAG_ADEN) == RESET);         //等待ADC1使能完成  

  

    ADC_DMACmd(ADC1, ENABLE);                                       //使能ADC_DMA  

    ADC_DMARequestModeConfig(ADC1, ADC_DMAMode_Circular);           //配置DMA请求模式为循环模式  

    ADC_StartOfConversion(ADC1);                                    //开启一次转换(必须)  

}  

  

void adc_gpio_init()  

{  

    GPIO_InitTypeDef gpio_init_structure;  

    //使能GPIO时钟  

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOC, ENABLE);  

  

    GPIO_StructInit(&gpio_init_structure);  

    //GPIOA                                                         //PA-0~3用作ADC  

    gpio_init_structure.GPIO_Pin = (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3);  

    gpio_init_structure.GPIO_Mode = GPIO_Mode_AN;                   //使用附加(模拟)功能  

    gpio_init_structure.GPIO_OType = GPIO_OType_PP;                 //推挽输出  

    gpio_init_structure.GPIO_Speed = GPIO_Speed_50MHz;              //Fast speed  

    gpio_init_structure.GPIO_PuPd= GPIO_PuPd_UP;                    //上拉  

    GPIO_Init(GPIOA, &gpio_init_structure);  

    //GPIOB  

    gpio_init_structure.GPIO_Pin = GPIO_Pin_0;                      //PB-0 用作ADC  

    GPIO_Init(GPIOB, &gpio_init_structure);  

    //GPIOC  

    gpio_init_structure.GPIO_Pin = (GPIO_Pin_4 | GPIO_Pin_5);       //PC-4~5用作ADC  

    GPIO_Init(GPIOC, &gpio_init_structure);  

}  

  

void adc_dma_init()  

{  

    DMA_InitTypeDef dma_init_structure;  

    NVIC_InitTypeDef nvic_init_structure;  

  

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);              //使能DMA时钟  

  

    nvic_init_structure.NVIC_IRQChannel = DMA1_Channel1_IRQn;       //选择DMA1通道中断  

    nvic_init_structure.NVIC_IRQChannelCmd = ENABLE;                //中断使能  

    nvic_init_structure.NVIC_IRQChannelPriority = 0;                //优先级设为0  

    NVIC_Init(&nvic_init_structure);  

  

    DMA_DeInit(DMA1_Channel1);                                      //复位DMA1_channel1  

    DMA_StructInit(&dma_init_structure);                            //初始化DMA结构体  

  

    dma_init_structure.DMA_BufferSize = DMA_BUFFER_SIZE;            //DMA缓存数组大小设置  

    dma_init_structure.DMA_DIR = DMA_DIR_PeripheralSRC;             //DMA方向:外设作为数据源  

    dma_init_structure.DMA_M2M = DISABLE;                           //内存到内存禁用  

    dma_init_structure.DMA_MemoryBaseAddr = (uint32)&adc_dma_tab[0];//缓存数据数组起始地址  

    dma_init_structure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//数据大小设置为Halfword  

    dma_init_structure.DMA_MemoryInc = DMA_MemoryInc_Enable;        //内存地址递增  

    dma_init_structure.DMA_Mode = DMA_Mode_Circular;                //DMA循环模式,即完成后重新开始覆盖  

    dma_init_structure.DMA_PeripheralBaseAddr = (uint32) &(ADC1->DR);//取值的外设地址  

    dma_init_structure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//外设取值大小设置为Halfword  

    dma_init_structure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址递增禁用  

    dma_init_structure.DMA_Priority = DMA_Priority_High;             //DMA优先级设置为高  

    DMA_Init(DMA1_Channel1, &dma_init_structure);  

  

    DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);                  //使能DMA中断  

    DMA_ClearITPendingBit(DMA_IT_TC);                                //清除一次DMA中断标志  

    DMA_Cmd(DMA1_Channel1, ENABLE);                                  //使能DMA1  

}  

  

void adc_timer_init()  

{  

    TIM_TimeBaseInitTypeDef timer_init_structure;  

    NVIC_InitTypeDef nvic_init_structure;  

  

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);            //使能TIM2时钟  

  

    nvic_init_structure.NVIC_IRQChannel = TIM2_IRQn;                //选择TIM2中断通道  

    nvic_init_structure.NVIC_IRQChannelCmd = ENABLE;                //使能TIM2中断  

    nvic_init_structure.NVIC_IRQChannelPriority = 0;                //优先级为0  

    NVIC_Init(&nvic_init_structure);  

  

    TIM_DeInit(TIM2);                                               //复位TIM2  

    TIM_TimeBaseStructInit(&timer_init_structure);                  //初始化TIMBASE结构体  

  

    timer_init_structure.TIM_ClockDivision = TIM_CKD_DIV1;          //系统时钟,不分频,48M  

    timer_init_structure.TIM_CounterMode = TIM_CounterMode_Up;      //向上计数模式  

    timer_init_structure.TIM_Period = 312;                          //每312 uS触发一次中断,开启ADC  

    timer_init_structure.TIM_Prescaler = 48-1;                      //计数时钟预分频,f=1M,systick=1 uS  

    timer_init_structure.TIM_RepetitionCounter = 0x00;              //发生0+1次update事件产生中断  

    TIM_TimeBaseInit(TIM2, &timer_init_structure);  

  

    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);                      //使能TIM2中断  

    TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);           //选择TIM2的update事件更新为触发源  

  

    TIM_Cmd(TIM2, ENABLE);                                          //使能TIM2  

}  

  

  

/****************************中断服务程序****************************/  

void TIM2_IRQHandler()  

{  

    if(TIM_GetITStatus(TIM2, TIM_IT_Update))            //判断发生update事件中断  

    {  

        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);     //清除update事件中断标志  

    }  

}  

  

void DMA1_Channel1_IRQHandler()  

{  

    if(DMA_GetITStatus(DMA_IT_TC))                      //判断DMA传输完成中断  

    {  

        if(sample_finish == 0)  

        {  

            sample_1[sample_index] = adc_dma_tab[0];  

            sample_2[sample_index] = adc_dma_tab[1];  

            sample_3[sample_index] = adc_dma_tab[2];  

            sample_4[sample_index] = adc_dma_tab[3];  

            sample_5[sample_index] = adc_dma_tab[5];  

            sample_6[sample_index] = adc_dma_tab[4];  

            sample_index++;  

        }  

        if(sample_index >= 128)                         //注意防止数组越界导致未知错误  

        {  

            sample_index = 0;  

            TIM_Cmd(TIM2, DISABLE);                     //完成周波采样,停止定时器  

            DMA_Cmd(DMA1_Channel1, DISABLE);            //完成周波采样,停止DMA  

            sample_finish = 1;                          //置采样完成标志位  

        }  

    }  

    DMA_ClearITPendingBit(DMA_IT_TC);                   //清除DMA中断标志位  

}


推荐阅读

史海拾趣

Dau Semiconductor Inc公司的发展小趣事

在成立初期,Dau Semiconductor Inc公司面临着诸多技术挑战。其中,如何实现芯片的低功耗设计是困扰公司发展的一个难题。为了解决这个问题,公司投入大量研发资源,不断探索新的技术和材料。经过数年的努力,公司终于成功突破了技术瓶颈,研发出了一款具有超低功耗的半导体芯片。这款芯片的推出,不仅为公司赢得了市场认可,也为公司在行业中树立了技术领先的形象。

e2v technologies公司的发展小趣事

为了进一步提升整体实力,e2v在发展过程中进行了多次收购与整合。这些收购不仅增强了公司的技术实力和市场竞争力,也为其带来了更多的客户资源。例如,e2v曾收购了一家专注于医疗成像技术的公司,这一举措使其在医疗成像领域取得了显著的进展。

BusBoard公司的发展小趣事

随着公司规模的扩大和产品线的丰富,BusBoard公司开始积极寻求市场扩张的机会。通过与国内外知名电子设备制造商建立合作关系,BusBoard公司的产品逐渐打入国际市场。同时,公司还积极参与行业交流和展会,与同行分享经验、探讨合作,共同推动电子行业的发展。这种合作共赢的理念使得BusBoard公司在市场上获得了更多的机会和资源。

Fujitsu America公司的发展小趣事

在物联网(IoT)和智能制造领域,Fujitsu America也展现出了卓越的创新能力和市场洞察力。公司通过与PTC等合作伙伴的紧密合作,将物联网技术和智能制造技术相结合,推出了一系列面向制造业的智慧工厂解决方案。这些解决方案不仅提高了生产效率和产品质量,还降低了生产成本和能源消耗,为制造业的数字化转型和可持续发展提供了有力支持。Fujitsu America的智慧工厂解决方案在北美市场得到了广泛应用和认可,为公司赢得了良好的市场口碑和品牌形象。

艾吉芯(Agertech)公司的发展小趣事

艾吉芯公司深知人才是企业发展的核心动力。因此,公司高度重视人才培养和团队建设。通过引进高素质的研发人才和管理人才,艾吉芯建立了一支高效、专业的团队。同时,公司还注重员工的培训和发展,为员工提供广阔的职业发展空间和良好的工作环境。

Bellnix Co Ltd公司的发展小趣事

Bellnix Co Ltd自创立之初,便以技术创新为核心竞争力。在电子元器件制造领域,公司不断投入研发,推出了一系列高性能、低成本的芯片产品。这些产品不仅在国内市场占据了一席之地,还成功打入了国际市场,赢得了众多客户的认可。随着技术的不断积累,Bellnix逐渐在行业内树立起了技术领先的形象,从而实现了公司的快速发展。

问答坊 | AI 解惑

红外协议资料

红外协议资料 …

查看全部问答>

51读写nandflash例程

51读写flash  下面是CYPRESS 68013上的一个读写samsung K9F1G的例子程序, 说明:程序针对mcu:cypress 68013,flash:samsung k9f1g08u,MCU运行于48M,对于其它频率,一些时序常数可能需要修改.程序实现了FLASH的CLEAR,WRITE,READ基本操作. /**** ...…

查看全部问答>

想买个开发板,大家给推荐推荐!

性价比高的吧,不能太贵,但是功能也不能太少!…

查看全部问答>

Stratix®IV 和HardCopy IV介绍 白皮书

Altera于2008年第二季度推出Stratix® IV和HardCopy® IV器件系列标志着世界上首款40-nm FPGA和业界唯一40-nm ASIC 无风险移植途径的诞生。 Altera 通过三年周密的规划和开发,并与代工线合作伙伴台积电(TSMC)协作,最终获得成功,交付定制 ...…

查看全部问答>

救助 用VHDL 设计一个指令寄存器 紧急 谢谢

救助 用VHDL  设计一个指令寄存器  紧急 谢谢  大家新年快乐哈…

查看全部问答>

谁给推荐一本wince5.0 bsp开发的书,现在觉得有本书比问人要方便一些;即使很简单的问题问人总也帮不上太多的忙

我现在入门学习wince, 但在怎么编译wince bsp这里遇到了问题. 发了几个帖,也许大家觉得太简单,没有人给个有意义的答案! 那高人们就给推荐一本书吧! 谢谢啊!…

查看全部问答>

wince sip手写输入法输出问题

各位大哥:     我的全屏输入程序是从定格输入的代码上改的,按理说手写识别之后将识别结果放到焦点的部分应该不受影响,但是现在程序编译可以通过,运行的时候没有焦点注入的效果。 我这儿是在识别线程函数DWORD ThreadProcRecognise( ...…

查看全部问答>

请教s3c2440功耗如何降低的问题?

我用的三星2440,在休眠时候把没用的IO都设置成了 input,并且上拉有效,奇怪的是电流一直在0.05A降不下来。 大家有什么高招吗? …

查看全部问答>

开机报警重装硬盘驱动

SMART Failure Predicted on Primary Master:IC35L040AVVA07-0 WARNING:Immediately back-up your data and replace your hard disk drive. A failure may be imminent . Press F1 to Continue ,DEL to enter Setup”, 硬盘驱动是怎么重 ...…

查看全部问答>

wince5.0子类化的疑问

Public Class ContextMenuHelper#Region \"事件\"Public Event ButtonDbClick(ByVal SubControl As Control, ByVal e As MouseEventArgs)Public Event ButtonClick(ByVal SubControl As Control, ByVal e As MouseEventArgs)#End RegionPublic Sub ...…

查看全部问答>