公告

大中华汽车电子生态圈社区并入开发者社区- 更多资讯点击此

Tip / 登入 to post questions, reply, level up, and achieve exciting badges. Know more

cross mob

【Aurix读书笔记】之ADC与DMA

【Aurix读书笔记】之ADC与DMA

a232007
Level 0
Level 0

书籍:《英飞凌多核单片机应用技术:AURIXTM三天入门篇》

首先感谢社区的管理大大给我提供了阅读这本《AURIXTM三天入门篇》的机会,看完这本书之后,我对英飞凌的AURIX系列单片机有了初步了解,并结合开发板做了一些调试,受益匪浅。

 

汽车电子领域对处理器性能的要求越来越高,而物理性能与现实操作的限制使得计算能力的提升不能仅仅依靠增加CPU的频率,为了控制功率损耗,引入了单芯片集成多个内核的方法。英飞凌AURIXTM系列的多核架构包含多达三颗独立32位Tricore处理内核,采用通过ISO26262认证的流程开发和设计,可高效满足ASIL-D级的要求;其中TC29x、TC27x和TC23x均内置一个硬件安全模块(HSM),可更好的满足未来汽车防止被盗窃、欺诈或篡改的安全要求。

AURIXTM多核单片机具有丰富的硬件资源接口、丰富的外设资源、强大的计算能力、精准的控制和全面的安全诊断功能。AURIXTM下的TC275T内部是三颗高性能的32位TricoreTMV1.6P/E CPU,集成了4MB的嵌入式FLASH,64KB的数据FLASH和472KB的片内RAM。

DMA原理:DMA是所有现代电脑的重要特色,他允许不同速度的硬件装置来沟通,而不需要依于CPU的大量 中断 负载。否则,CPU需要从来源把每一片段的资料复制到暂存器,然后把他们再次写回到新的地方。在这个时间中,CPU对于其他的工作来说就无法使用。DMA传输重要地将一个内存区从一个装置复制到另外一个。当CPU初始化这个传输动作,传输动作本身是由DMA控制器来实行和完成。典型的例子就是移动一个外部内存的区块到芯片内部更快的内存去。像是这样的操作并没有让处理器工作拖延,反而可以被重新排程去处理其他的工作。DMA传输对于高效能 嵌入式系统算法和网络是很重要的。

DMA方式,即外设在专用的接口电路DMA控制器的控制下直接和存储器进行高速数据传送。采用DMA方式时,如外设需要进行数据传输,首先向DMA控制器发出请求,DMA再向CPU发出总线请求,要求控制系统总线。CPU响应DMA控制器的总线请求并把总线控制权交给DMA,然后在DMA的控制下开始利用系统总线进行数据传输。数据传输结束后,DMA交还回总线控制权。

DMA操作步骤:
(1) DMA控制器的初始化
(2) DMA数据传送
(3) DMA结束
DMA初始化预置如下信息:一是指定I/O设备对外设"读"还是"写",即指定其控制/状态寄存器中相应的控制位;二是数据应传送至何处,指定其地址的首地址;三是有多少数据字需要传送。

下面的例子实现了DMA与ADC的联合应用。通过将DMA通道设置为连续模式,将源地址设置为ADC模块的数组,目的地址设置为DSPR,实现由ADC向DSPR的数据搬运。

 

IfxVadc_Adc vadc;

IfxVadc_Adc_Group adcGroup;                               //VADC group handle

IfxVadc_Adc_Channel adcChannel[8];

Ifx_VADC_RES conversionResult;

 

static uint16 vadcResultBuffer[NUM_SCANNED_CHANNELS];

uint32 interrupt_flag = 0;

 

IFX_INTERRUPT(dmaCh0ISR, 0, DMA_CHANNEL1_ISR_PRIO)

{

       //...

       // do something with the conversion results in vadcResultBuffer[]

       //...

 

       //重新初始化DMA通道的目标地址

       DMA_DADR001.U = (uint32)&vadcResultBuffer[0];

       DMA_CHCFGR001.B.TREL = 8;  //transfer reload value

 

       IfxPort_togglePin(&MODULE_P33,8);

       interrupt_flag++;

 

}

 

 

void Adc_module_config(void)//模块——group——adc_channel——dma_channel三部曲

{

       //Adc模块初始化

       IfxVadc_Adc_Config adcConfig;

       IfxVadc_Adc_initModuleConfig(&adcConfig, &MODULE_VADC);

 

       IfxVadc_Adc_initModule(&vadc, &adcConfig);

 

       //Group的初始化,adc的group是啥?

       IfxVadc_Adc_GroupConfig adcGroupConfig;

       IfxVadc_Adc_initGroupConfig(&adcGroupConfig, &vadc);

 

       adcGroupConfig.groupId = IfxVadc_GroupId_0;//groupID都是0,第一个转换器

       adcGroupConfig.master  = adcGroupConfig.groupId;

       //If master is different from groupId, then the group is configured as slave

 

       //使能所有的裁决需求

       adcGroupConfig.arbiter.requestSlotQueueEnabled                      = TRUE; //enable Queue mode顺序、扫描、后台三种仲裁

       adcGroupConfig.arbiter.requestSlotScanEnabled                 = TRUE; //enable Scan mode

       adcGroupConfig.arbiter.requestSlotBackgroundScanEnabled = TRUE; //enable Background scan

 

       //使能所有gates处于always模式

       adcGroupConfig.queueRequest.triggerConfig.gatingMode = IfxVadc_GatingMode_always;

       adcGroupConfig.scanRequest.triggerConfig.gatingMode  = IfxVadc_GatingMode_always;

       adcGroupConfig.backgroundScanRequest.triggerConfig.gatingMode = IfxVadc_GatingMode_always;

 

       IfxVadc_Adc_initGroup(&adcGroup, &adcGroupConfig);//adcGroup转换器的初始化完成

       //请求确定通道,转换控制通道的转换参数

 

       {

 

              IfxVadc_Adc_ChannelConfig adcChannelConfig[8];

 

              int chnIx=0;

              for(chnIx=0; chnIx<NUM_SCANNED_CHANNELS; ++chnIx){

 

                     IfxVadc_Adc_initChannelConfig(&adcChannelConfig[chnIx], &adcGroup);//把adcgroup和channel联系起来

                     adcChannelConfig[chnIx].channelId = (IfxVadc_ChannelId)(chnIx);

                     adcChannelConfig[chnIx].resultRegister = IfxVadc_ChannelResult_0;

 

                     adcChannelConfig[chnIx].resultServProvider = IfxSrc_Tos_dma;

                     adcChannelConfig[chnIx].resultSrcNr = IfxVadc_SrcNr_group0;//Service node of the result trigger

                     adcChannelConfig[chnIx].resultPriority = VADC_DMA_CHANNEL;

 

                     IfxVadc_Adc_initChannel(&adcChannel[chnIx], &adcChannelConfig[chnIx]);

 

                     //add to autoscan

                     unsigned channels = (1 << adcChannelConfig[chnIx].channelId); //0-7依次左移一位

                     unsigned mask = channels;

                     boolean continuous = TRUE;

                     IfxVadc_Adc_setScan(&adcGroup, channels, mask, continuous);

              }

 

              IfxVadc_Adc_startScan(&adcGroup);

 

              IfxPort_setPinMode(&MODULE_P33, 8,  IfxPort_Mode_outputPushPullGeneral);

       }

}

 

void ADC_Scan(void)

{

       unsigned char chnIx;

       IfxVadc_Adc_startScan(&adcGroup);

}

 

 

IfxDma_Dma dma;

IfxDma_Dma_Channel dmaChn;

void Dma_channel_config(void)

{

       IfxDma_Dma_Config dmaConfig;

       IfxDma_Dma_initModuleConfig(&dmaConfig, &MODULE_DMA);

 

       IfxDma_Dma_initModule(&dma, &dmaConfig);

 

       {

              //不光要配置adc的channel还要配置dma的channel

              IfxDma_Dma_ChannelConfig chnCfg;

              IfxDma_Dma_initChannelConfig(&chnCfg, &dma);

 

              //选择要使用的DMA通道

              chnCfg.channelId = IfxDma_ChannelId_1; //共64个通道

              chnCfg.hardwareRequestEnabled = TRUE;  //注意是硬件触发模式

 

              //中断配置

              chnCfg.channelInterruptEnabled = TRUE; //所有bit数据传送完之后DMA发出服务请求

              chnCfg.channelInterruptPriority = DMA_CHANNEL1_ISR_PRIO;//优先级在Ifx_IntPrioDef.h中定义

              chnCfg.channelInterruptTypeOfService = IfxSrc_Tos_cpu0;//这个地方dma通道的服务者还是cpu

 

              //源地址与目标地址

              chnCfg.sourceAddress                        = (uint32)&VADC_G0_RES0; // first result register

              chnCfg.sourceCircularBufferEnabled    = TRUE;

              chnCfg.sourceAddressCircularRange          = IfxDma_ChannelIncrementCircular_1; //保持这个地址

 

              chnCfg.destinationAddress                  = (uint32)&(vadcResultBuffer[0]);

              chnCfg.destinationAddressIncrementStep= IfxDma_ChannelIncrementStep_1;       //每次写数据时地址增量为2个byte

 

              //move size, transfer count and request/operation mode

              chnCfg.moveSize   = IfxDma_ChannelMoveSize_16bit;//1 DMA move is 16 bit wide

              chnCfg.transferCount = NUM_SCANNED_CHANNELS;//依次transfer传输8个

              chnCfg.requestMode   = IfxDma_ChannelRequestMode_oneTransferPerRequest;

              chnCfg.operationMode = IfxDma_ChannelOperationMode_continuous;                          //硬件请求使能保持set在transaction

 

              IfxDma_Dma_initChannel(&dmaChn, &chnCfg);

 

              IfxCpu_Irq_installInterruptHandler(&dmaCh0ISR, DMA_CHANNEL1_ISR_PRIO);//!!这是软件中断,要把Ifx_Cfg.h中的#define IFX_USE_SW_MANAGED_INT注释去掉,否则连接不上

 

              IfxCpu_enableInterrupts();

 

       }

}

 

//这段DMA服务代码的总功能:一旦有新结果产生,就把AD转换的结果搬运到DSPR中。

 


0 点赞
6830 次查看
4 评论