历史上的今天
返回首页

历史上的今天

今天是:2024年10月06日(星期日)

2018年10月06日 | STM32F407ADC多通道+定时器触发+DMA模式设置

2018-10-06 来源:eefocus

#include "adc.h"

u8 UpdataTIM = 0;        //更新TIM2定时器标志

u16 CurrentFreq = 500;//默认市电频率,单位为0.1hz

ADBASE_TYPE uAD_Buff_A[ADC_CHANNEL];        //ADC采集缓存A

ADBASE_TYPE uAD_Buff_B[ADC_CHANNEL];        //ADC采集缓存B

//考虑到可能出现的数据处理时间较长的问题,临时添加缓存

//u16 uAD_IN_BUFF[ADC_BUFFSIZE][ADC_CHANNEL];

ADBASE_TYPE *CurrentBuffPtr = NULL;        //当前缓存指针

static void ADCInit_GPIO(void)

{

    GPIO_InitTypeDef  GPIO_InitStructure;

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);//使能GPIOF时钟

    //ADC通道初始化

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|  \

                                    GPIO_Pin_9|GPIO_Pin_10; //PF3,PF4,PF5,PF6,PF7,PF8,PF9,PF10 ADC通道

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;  //模拟输入

    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;  //不带上下拉

    GPIO_Init(GPIOF, &GPIO_InitStructure);  //初始化     

}

static void ADCInit_ADC(void)

{

    ADC_CommonInitTypeDef ADC_CommonInitStructure;

    ADC_InitTypeDef       ADC_InitStructure;

    

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE); //使能ADC3时钟

    

    RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC3,ENABLE);      //ADC3复位

    RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC3,DISABLE); //复位结束     

    ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;//独立模式

    ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; //两个采样阶段之间的延迟5个时钟(三重模式或双重模式下使用)

    ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; //DMA失能(对于多个ADC模式)

    ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;//预分频4分频。ADCCLK=PCLK2/4=84/4=21Mhz,ADC时钟最好不要超过36Mhz 

    ADC_CommonInit(&ADC_CommonInitStructure);//初始化

    

    ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//12位模式

    ADC_InitStructure.ADC_ScanConvMode = ENABLE;//扫描模式(多通道ADC采集要用扫描模式)    

    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//关闭连续转换

//    ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; //软件触发

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

    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_TRGO;  //定时器事件2触发ADC

    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右对齐    

    ADC_InitStructure.ADC_NbrOfConversion = ADC_CHANNEL;    //8个转换在规则序列中

    ADC_Init(ADC3, &ADC_InitStructure);//ADC初始化

    

    //连续模式下,通道的配置

    ADC_RegularChannelConfig(ADC3, ADC_Channel_9, 1, ADC_SampleTime_15Cycles);  //PF3,VIN1,通道9,UA,rank=1,表示连续转换中第一个转换的通道,采样时间15个周期(如果数据不稳定可以延时采样时间)

    ADC_RegularChannelConfig(ADC3, ADC_Channel_14, 2, ADC_SampleTime_15Cycles); //PF4,VIN2,通道14,UB

    ADC_RegularChannelConfig(ADC3, ADC_Channel_15, 3, ADC_SampleTime_15Cycles); //PF5,VIN3,通道15,AC220

    ADC_RegularChannelConfig(ADC3, ADC_Channel_4, 4, ADC_SampleTime_15Cycles);     //PF6,VIN4,通道4,I0

    ADC_RegularChannelConfig(ADC3, ADC_Channel_5, 5, ADC_SampleTime_15Cycles);     //PF7,VIN5,通道5,IA

    ADC_RegularChannelConfig(ADC3, ADC_Channel_6, 6, ADC_SampleTime_15Cycles);     //PF8,VIN6,通道6,IB

    ADC_RegularChannelConfig(ADC3, ADC_Channel_7, 7, ADC_SampleTime_15Cycles);     //PF9,VIN7,通道7,IC

    ADC_RegularChannelConfig(ADC3, ADC_Channel_8, 8, ADC_SampleTime_15Cycles);     //PF10,VIN8,通道8,暂时未接入信号

    ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE); //连续使能DMA

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

    ADC_Cmd(ADC3, ENABLE);//开启AD转换器    

}

static void ADCInit_DMA(void)

{

    DMA_InitTypeDef  DMA_InitStructure;

    

    //时钟

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);

    

    //DMA设置

    DMA_InitStructure.DMA_Channel = DMA_Channel_2; //选择通道号

    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(ADC3->DR); //外围设备地址,ADC_DR_DATA规则数据寄存器

    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)(u16 *)uAD_Buff_A; //DMA存储器地址,自己设置的缓存地址

    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; //传输方向,外设->存储器

    DMA_InitStructure.DMA_BufferSize = ADC_BUFFSIZE * ADC_CHANNEL; //DMA缓存大小,数据传输量32*8

    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设是否为增量模式

    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //存储器是否为增量模式

    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //外设数据长度半个字(16位)

    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //存储器数据长度半字(16位)

    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //DMA模式,普通模式、循环模式,还有双缓冲模式,需要特殊设置

    DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMA优先级,高优先级

    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; //不使用FIFO

    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; //FIFO阈值

    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; //存储器突发,单次传输

    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; //外设突发,单次传输

    DMA_Init(DMA2_Stream0, &DMA_InitStructure); //初始化DMA2_Stream0,对应为ADC3

    //双缓冲模式设置

    DMA_DoubleBufferModeConfig(DMA2_Stream0,(uint32_t)(u16 *)(uAD_Buff_B),DMA_Memory_0);    //DMA_Memory_0首先被传输

    DMA_DoubleBufferModeCmd(DMA2_Stream0,ENABLE);

    

    //设置DMA中断

    DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TC); //清除中断标志   

    DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE); //传输完成中断                                       

    DMA_Cmd(DMA2_Stream0, ENABLE); //使能DMA

    

}

void ADCInit_Timer(void)

{

    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

    //时钟

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);          

    //失能定时器

    TIM_Cmd(TIM2, DISABLE);

    TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); //初始化定时器

    

    //定时器设置,T=(84 * 625) / 84M = 625us = 20ms/32,50Hz信号,每周期采样32个点,采样频率1600

    TIM_TimeBaseStructure.TIM_Prescaler = 84-1; //分频系数,TIM2时钟在分频系数不为1时,时钟是APB1时钟的两倍84M

    TIM_TimeBaseStructure.TIM_Period = 312500/CurrentFreq - 1; //周期值1M/32=31250,CurrentFreq单位为0.1hz,因此需扩大10倍

    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分频因子

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

    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //初始化定时器2

    

    //使能定时器中断    

    TIM_ARRPreloadConfig(TIM2, ENABLE); //允许TIM2定时重载

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

//    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //配置TIM2中断类型

    

    //使能TIM2

    TIM_Cmd(TIM2, ENABLE); 

    DebugLog("Enable TIM2, Set frequency is %d.", CurrentFreq);

}

static void ADCInit_Nvic(void)

{

    NVIC_InitTypeDef NVIC_InitStructure;

    

    //定时器中断设置

    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;  //定时器TIM2中断通道

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;  //抢占优先级0

    NVIC_InitStructure.NVIC_IRQChannelSubPriority =1;        //子优先级1

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //IRQ通道使能

    NVIC_Init(&NVIC_InitStructure);    //根据指定的参数初始化NVIC寄存器    

    

    //DMA中断设置

    NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;  //DMA2_Stream0中断

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;  //抢占优先级1

    NVIC_InitStructure.NVIC_IRQChannelSubPriority =1;        //子优先级1

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //IRQ通道使能

    NVIC_Init(&NVIC_InitStructure);    //根据指定的参数初始化NVIC寄存器    

}

                                                           

void ADCInit(void)

{

    ADCInit_GPIO();

    ADCInit_DMA();

    ADCInit_ADC();

    ADCInit_Nvic();

    DebugLog("ADC Init is finish.");

}    

void TIM2_IRQHandler(void)  

{

  OSIntEnter(); //进入中断    

    

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

    {         

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

//    ADC_SoftwareStartConv(ADC1);      

    }

    

    OSIntExit();  //退出中断  

}

void DMA2_Stream0_IRQHandler(void)  

{

    u16 period = 0;

    

  OSIntEnter(); //进入中断 

    if(DMA_GetITStatus(DMA2_Stream0, DMA_IT_TCIF0))  //判断DMA传输完成中断  

    {

         DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);

//         DMA_Cmd(DMA2_Stream0, ENABLE); //使能DMA,连续模式下不需要该使能

         //数据转移程序

         if(DMA_GetCurrentMemoryTarget(DMA2_Stream0) == DMA_Memory_0)

         {

             CurrentBuffPtr = uAD_Buff_A;

         }

         else

         {

             CurrentBuffPtr = uAD_Buff_B;

         }

         //遥测任务等待该信号量

         OSSemPost(SemAD);

         

         //判断是否更新TIM2

         if(UpdataTIM)

         {

             period = 312500/CurrentFreq - 1;        //计算采样频率1M/32=31250;32为采样点数,31250/freq=采样周期

             TIM_ARRPreloadConfig(TIM2, DISABLE); //关闭TIM2定时重载

             TIM2->ARR = period ;        //更新定时器周期

             TIM_ARRPreloadConfig(TIM2, ENABLE);     //打开TIM2定时重载

         }

    }

    OSIntExit();  //退出中断  

}


推荐阅读

史海拾趣

Hamlin ( Littelfuse )公司的发展小趣事

故事一:市场定位与技术创新

HAHN - Elektrobau GmbH & Co KG公司自成立以来,便在电子行业中找到了自己的独特定位,专注于生产面向特定应用的特种变压器线圈。起初,公司通过深入研究市场需求,发现传统变压器线圈在特定应用中存在效率低下、体积过大等问题。于是,HAHN投入大量资源进行技术研发,优化产品设计,成功开发出了一系列高效、紧凑的特种变压器线圈,迅速赢得了市场的认可。这一举措不仅巩固了公司在电子行业中的地位,也为后续的发展奠定了坚实的基础。

故事二:合作与共赢

在发展过程中,HAHN深知合作的重要性。公司积极与上下游企业建立紧密的合作关系,共同推动技术进步和产业升级。例如,HAHN与多家知名电子制造商建立了长期合作关系,共同开发新产品,优化生产工艺。通过这些合作,HAHN不仅获得了宝贵的市场信息和技术支持,还成功地将自身产品打入了更广阔的市场领域。同时,公司还积极与供应商和分包商合作,通过优化供应链管理,降低了生产成本,提高了生产效率,实现了共赢发展。

故事三:全球化战略

随着电子行业的全球化趋势日益明显,HAHN也开始了自己的全球化战略。公司不仅在欧洲市场取得了显著成绩,还积极向亚洲、北美等市场扩张。为了更好地服务全球客户,HAHN在多个国家和地区设立了分支机构,并建立了完善的销售和服务网络。通过这些举措,HAHN成功地将自己的产品和服务推向了全球市场,进一步提升了品牌知名度和市场份额。

故事四:品质与服务的双重保障

在电子行业中,品质和服务是企业生存和发展的关键。HAHN深知这一点,因此始终将品质和服务放在首位。公司建立了严格的质量控制体系,对每一个环节都进行严格的把关,确保产品质量达到最高标准。同时,公司还注重提升客户服务水平,建立了专业的客户服务团队,为客户提供全方位、个性化的服务。这些举措不仅赢得了客户的信赖和好评,也为公司赢得了更多的业务机会。

故事五:持续研发与创新

面对日新月异的电子行业技术,HAHN始终保持着高度的敏锐性和前瞻性。公司不断加大研发投入,引进高端人才和先进设备,致力于新技术、新产品的开发。通过持续的研发和创新,HAHN不断推出具有自主知识产权的新产品和技术方案,为电子行业的发展注入了新的活力。同时,公司还积极参与行业标准的制定和修订工作,推动行业技术进步和产业升级。这些努力不仅提升了公司的核心竞争力,也为公司的可持续发展奠定了坚实的基础。

Computer Conversions Corp公司的发展小趣事

Computer Conversions Corp非常重视人才的培养和团队建设。公司定期组织内部培训和技术交流活动,鼓励员工分享经验和创新想法。同时,公司还建立了完善的激励机制,为员工提供广阔的发展空间。这种以人为本的管理理念,不仅增强了团队的凝聚力和创新力,也为公司的持续发展注入了强大的动力。通过这些举措,Computer Conversions Corp打造出了一支高素质、高效率的技术团队,为公司的长远发展奠定了坚实的基础。

ELANTEC (Renesas )公司的发展小趣事

Renesas Electronics的前身可以追溯到1958年,当时日立制作所成立了半导体部门。随着技术的不断进步和市场的扩大,该部门逐渐发展壮大,成为日立公司内的一个重要业务部门。进入20世纪90年代,随着半导体市场的竞争加剧,日立公司决定将半导体业务独立出来,以便更加灵活地应对市场变化。1999年,日立半导体部门正式更名为ELANTEC,开始了独立发展的道路。

Cermetek Microelectronics公司的发展小趣事

随着公司规模的扩大和业务的增长,Cermetek Microelectronics公司开始实施国际化战略。公司积极拓展海外市场,与多个国家和地区的客户建立了合作关系。同时,公司还在海外设立了研发中心和生产基地,以更好地服务全球客户。这种全球布局不仅提升了公司的国际竞争力,也为公司的长远发展奠定了坚实的基础。

Handok Co Ltd公司的发展小趣事

在追求经济效益的同时,Cermetek Microelectronics公司也积极履行社会责任。公司注重环保和可持续发展,采用环保材料和生产工艺,减少对环境的影响。此外,公司还积极参与社会公益事业,为社会做出贡献。这种负责任的态度不仅赢得了社会各界的认可,也为公司的长远发展注入了正能量。

这五个故事展示了Cermetek Microelectronics公司在电子行业中的发展历程和取得的成就。通过技术积累、品质管理、持续创新、国际化战略和社会责任等方面的努力,公司逐渐在微电子领域树立起了自己的品牌形象和市场地位。

Caddell-Burns Manufacturing公司的发展小趣事

在竞争激烈的电子行业中,质量管理是企业生存和发展的关键。Caddell-Burns Manufacturing公司深知这一点,因此他们始终将质量放在首位。公司建立了严格的质量管理体系,从原材料采购到产品生产、检验、包装等各个环节都进行严格把关。同时,公司还定期对员工进行质量培训,提高他们的质量意识和操作技能。这些措施确保了公司产品的稳定性和可靠性,赢得了客户的信赖。

问答坊 | AI 解惑

[个人经验谈]PIC 的硬件死锁 ??

使用 PIC 单片机 去设计工控电路,最头痛的问题,就是 PIC 单片机在受干扰后经常硬件死锁,大部份人归咎于 “CMOS的可控硅效应” 因而产生死锁现象,一般都认为 ‘死锁后硬件复位都是无效的.只有断电。’ 但是一个成熟的商品,那须要你去断电呢? 就好像 ...…

查看全部问答>

在wince 5.0中看到键盘驱动的驱动中问题

BOOL WINAPI KeyPad_Entry(     UINT uiPddId,     PFN_KEYBD_EVENT pfnKeyPadEvent,     PKEYBD_PDD *ppKeybdPdd     ) {     SETFNAME(_T(\"KeyPad_Entry\"));     BOOL f ...…

查看全部问答>

pdu编码,添加上86后,为什么发送不到某些号上去

如题 具体可以参看 [url=http://blog.eeworld.net/lbjfeng/archive/2009/12/05/4943109.aspx][/url] 后面有具体的说明…

查看全部问答>

CE6下应用使用驱动回传过来的内存地址问题!

软硬件环境:WinCE6 + Pxa310/300 问题: 一个测试overlay2的小应用,在CE5下面使用没有问题,但是CE6下面使用的时候会出现异常。具体是这样的,应用中通过如下方式获得显示驱动回传过来的地址指针, ExtEscape(m_hdc,GET_OVERLAY2_ADDRESS,0,NU ...…

查看全部问答>

关于ADUC812D 功能

有谁知道ADUC812的详细功能 ,谢谢!…

查看全部问答>

请问inline是什么关键字?

                                 为什么IAR编译不过去,得全删除。ADS可以编译通过。…

查看全部问答>

关于异步复位.同步释放

小生初学FPGA,在特权同学编的书《深入浅出FPGA》里看到复位一章的时候,有几个问题不懂,希望能有大大帮忙~异步复位 同步释放异步复位我能理解 但这图里的同步释放怎么解释呢? 我感觉还是会产生亚稳态啊…

查看全部问答>

stm32的启动文件在keil MDK

startup_stm32f10x_hd.S(1): error: A1167E: Invalid line start startup_stm32f10x_hd.S:     1 00000000 /**startup_stm32f10x_hd.S(2): error: A1137E: Unexpected characters at end of linestartup_stm32f10x_hd.S:  ...…

查看全部问答>

PCB的器件布局注意事项

  在PCB板的设计中,布局是一个非常重要的环节。系统布局的好坏将直接影响到布线的效果,合理的布局可以有以下优点:   · 节省电路板的空间,以减少成本;   · 使系统的体积变小;   · 使系统的可靠性提高。   不好的PCB ...…

查看全部问答>