s32k344 DMA与ADC以及一些DMA注意事项

不管是软件触发还是硬件触发,通过DMA搬运时,通过函数Adc_Ipw_StartDmaOperation来初始化源地址和目的地址。

S32K344中每个ADC实例只能用一个DMA通道,当一个GROUP包含多个转换通道时,通过DMA的S/G功能实现。

多个ADC通道只有最后一个ADC通道会触发DMA请求,一个MAjor loop完成后,自动装载下一个TCD,也就是说一个硬件触发DMA请求以及通道-1软件DMA触发请求。

 同时在设置多个通道TCD时候,也设置了不同触发源。

 可以看出,第一个TCD的不允许软件出发,只允许硬件触发,不允许产生MAJOR LOOP        中断。
第2个TCD到n-1个TCD,只允许软件出发,不允许产生MAJOR LOOP中断。
最后一个TCD,只允许软件触发,允许产生MAJOR LOOP中断。

所有通道搬运完后只产生一次中断

ADC结果搬运,源地址是一直不变的,变得是目的地址,TCD的更新是在中断中实现的。

如果通道数过多,消耗的时间越多。其他代码执行一会就又要处理中断,而且这个中断很耗时,这就导致其他代码执行很慢,无法适用于实时操作系统。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
S32K344是一款高性能的汽车MCU,它集成了多个DMA通道和ADC模块,可以方便地实现ADC采集电压数据并通过DMA传输。下面是一个简单的示例代码,用于演示如何实现ADC采集电压数据并通过DMA传输: ```c #include "S32K344.h" #define ADC_CHANNEL 0 #define DMA_CHANNEL 0 #define BUFFER_SIZE 16 uint16_t adc_data[BUFFER_SIZE]; uint16_t dma_data[BUFFER_SIZE]; void init_adc() { /* 初始化ADC模块 */ ADC_0.MCR.B.PWDN = 0; /* 使能ADC模块 */ ADC_0.MCR.B.ADCLKSEL = 2; /* 选择ADC时钟源为主时钟 */ ADC_0.MCR.B.MODE = 0; /* 选择单次采样模式 */ ADC_0.MCR.B.ACKO = 0; /* 禁止自动校准 */ ADC_0.MCR.B.SMPLTS = 15; /* 设置采样时间 */ ADC_0.MCR.B.ADTRGSEL = 0; /* 选择软件触发 */ ADC_0.MCR.B.NSTART = 1; /* 启动ADC */ /* 配置ADC通道 */ ADC_0.CTR[ADC_CHANNEL].B.CHDSEL = ADC_CHANNEL; /* 选择采样通道 */ ADC_0.CTR[ADC_CHANNEL].B.CHNCFG = 0x100; /* 选择单端输入模式 */ ADC_0.CTR[ADC_CHANNEL].B.DIFF = 0; /* 选择单端输入模式 */ } void init_dma() { /* 初始化DMA模块 */ DMAMUX.CHCFG[DMA_CHANNEL].B.ENBL = 0; /* 禁止DMA通道 */ DMAMUX.CHCFG[DMA_CHANNEL].B.TRIG = 0x1F; /* 选择ADC转换完成事件触发 */ DMAMUX.CHCFG[DMA_CHANNEL].B.SOURCE = 0x40; /* 选择ADC数据寄存器为源地址 */ DMAMUX.CHCFG[DMA_CHANNEL].B.CHANNEL = DMA_CHANNEL; /* 设置DMA通道号 */ DMA.CH[DMA_CHANNEL].SAR.R = (uint32_t)&ADC_0.CDR[ADC_CHANNEL].B.CDATA; /* 设置源地址为ADC数据寄存器 */ DMA.CH[DMA_CHANNEL].DAR.R = (uint32_t)dma_data; /* 设置目标地址为DMA缓冲区 */ DMA.CH[DMA_CHANNEL].SSIZE.B.SIZE = 1; /* 设置源数据大小为2字节 */ DMA.CH[DMA_CHANNEL].DSIZE.B.SIZE = 1; /* 设置目标数据大小为2字节 */ DMA.CH[DMA_CHANNEL].SOFF.R = 0; /* 源地址偏移为0 */ DMA.CH[DMA_CHANNEL].DOFF.R = 2; /* 目标地址偏移为2 */ DMA.CH[DMA_CHANNEL].NBYTES.MLNO.R = BUFFER_SIZE * 2; /* 设置传输数据大小 */ DMA.CH[DMA_CHANNEL].CR.B.SMOD = 0; /* 源地址模式为自增 */ DMA.CH[DMA_CHANNEL].CR.B.DMOD = 0; /* 目标地址模式为自增 */ DMA.CH[DMA_CHANNEL].CR.B.SIZE = 1; /* 传输数据大小为2字节 */ DMA.CH[DMA_CHANNEL].CR.B.DIR = 1; /* 传输方向为从源到目标 */ DMA.CH[DMA_CHANNEL].CR.B.CE = 1; /* 使能循环传输 */ } int main() { init_adc(); init_dma(); while (1) { ADC_0.MCR.B.NSTART = 1; /* 启动ADC转换 */ while (ADC_0.CDR[ADC_CHANNEL].B.VALID == 0); /* 等待转换完成 */ } } ``` 在上面的代码中,我们首先通过`init_adc()`函数初始化了ADC模块,并选择了需要采样的通道。然后通过`init_dma()`函数初始化了DMA通道,并将ADC数据寄存器设置为源地址,DMA缓冲区设置为目标地址。最后,在主函数中通过循环不断地启动ADC转换,并等待转换完成。每次转换完成后,DMA会自动将采样数据传输到指定的缓冲区中。 需要注意的是,在使用DMA传输数据时,必须先使能DMA通道,并配置好DMA通道的相关参数,才能启动ADC转换。同时,由于采样数据是以16位的方式存储的,因此需要将DMA传输的数据大小设置为2字节。此外,由于S32K344集成了多个DMA通道和ADC模块,我们可以根据实际需要选择不同的通道和模块进行采样和传输。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值