F28335 ADC配置代码模块及其排序方式介绍

从问题出发:

第一,在F28335内核中,通过多路复用后有16个模拟转换输入通道,多路复用实际是用时间换资源, 16个通道肯定是不能并行转换的,这时候DSP是怎么处理的?

第二,AD模块转换的时候,实际采用2个采样保持器,2个采样保持器的结果肯定也不能同时转换,都是分时转换,而实际应用中,经常会需要同时读取两个信号,这个时候DSP是怎么实现同时采到数据的?

这16个输入通道,2路采样保持器,如何组合,先后转换顺序如何确定,如何响应触发源就成了需要解决的问题。

实际应用中,DSP是通过两个8通道排序寄存器(SEQ1和SEQ2)来完成的。

下面就详细的介绍它的排序原理和过程:

 

1 ADC排序器操作

SEQ1,SEQ2,是两个8状态排序其,能够分别完成8个通道的A/D转换通道的排序管理。A/D模块每次收到触发源的开始转换请求(SOC)之后,就会通过排序器来自动完成多路转换,将模拟信号引入采样保持器,并且在转换完成之后,将转换的结果存入结果寄存器。简而言之,他们的作用就相当于掌权者,分配了所有通道的优先级,决定那个通道先转换先存储。

其工作方式分为两种,

  • 级联工作方式
  • 双排序器工作方式。

这两种工作方式最大的区别:

  1. 级联方式相当于串行模式,将两个8路串联成了一个16路,只能一个一个来,而双排序器的工作方式就多了一条通道,相当于并行模式,能够保证信号的同时性。
  2. 初始化最多通道数时,级联方式有效通道数为16,而双排序的有效通道数为8
  3. 级联方式只用一个触发源,双排序需要两个

所以级联的方式比较简单,而双排序的就比较复杂一些。

补充:采样方式介绍

顺序采样:0-7或者0-15都是同一时间只转换一路信号

同步采样:0-7的一个通道和9-15的一个通道同时转换信号,但是必须要有相同的偏移量,比如ADCINA4和ADCINB4就可以,但是ADCINA7和ADCINB6就不能同一时刻转换。

2 级联工作方式的配置过程

在级联工作方式下,2个8状态的排序器构成一个16状态的排序器,

第一步:设置ADC时钟 ,运行模式和采样模式,一般为12.5M,非连续运行模式和顺序采样

第二步:设置级联的工作方式

第三步:设置最大通道数

第四步:使能SEQ1中断,通过ADCCHSELSEQx来排转换顺序。

代码例子+注释: 级联方式下的16通道打开操作

   AdcRegs.ADCTRL1.bit.ACQ_PS = ADC_SHCLK;  //设置ADC时钟
   AdcRegs.ADCTRL3.bit.SMODE_SEL= 0;        //设置为顺序采样
   AdcRegs.ADCTRL1.bit.CONT_RUN= 0;         //设置为非连续运行方式
   AdcRegs.ADCTRL1.bit.SEQ_CASC = 1;        //设置为级联工作方式
   AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 15;   //设置最大通道数
   AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x0;   //SEQ1对应CONV00-03
   AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x1;
   AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 0x2;
   AdcRegs.ADCCHSELSEQ1.bit.CONV03 = 0x3;
   AdcRegs.ADCCHSELSEQ2.bit.CONV04 = 0x4;   //SEQ2对应CONV04-07
   AdcRegs.ADCCHSELSEQ2.bit.CONV05 = 0x5;
   AdcRegs.ADCCHSELSEQ2.bit.CONV06 = 0x6;
   AdcRegs.ADCCHSELSEQ2.bit.CONV07 = 0x7;
   AdcRegs.ADCCHSELSEQ3.bit.CONV08 = 0x8;   //SEQ3对应CONV08-11
   AdcRegs.ADCCHSELSEQ3.bit.CONV09 = 0x9;
   AdcRegs.ADCCHSELSEQ3.bit.CONV10 = 0xA;
   AdcRegs.ADCCHSELSEQ3.bit.CONV11 = 0xB;
   AdcRegs.ADCCHSELSEQ4.bit.CONV12 = 0xC;   //SEQ4对应CONV012-05
   AdcRegs.ADCCHSELSEQ4.bit.CONV13 = 0xD;
   AdcRegs.ADCCHSELSEQ4.bit.CONV14 = 0xE;
   AdcRegs.ADCCHSELSEQ4.bit.CONV15 = 0xF;

   AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 0x1;     //打开SEQ1中断
   AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1 = 0x1;   //使能 PWMA SOC触发

看到以上代码,肯定会想几个问题:

1,为什么只有SEQ1和SEQ2两个排序器,却出现ADCCHSELSEQ3和ADCCHSELSEQ4出来?

这是因为这是另外一个寄存器,这是两个概念的,DSP本身硬件上是有SEQ1和SEQ2的,而ADCCHSELSEQx时管理多通道的4个寄存器.

2,为什么只用开SEQ1中断而不开SEQ2中断?

这是因为在级联模式下,SEQ1的8状态排序和SEQ2的8状态排序公用一个触发源,所以只用开SEQ1的中断就够了。

3,级联方式下是按照什么顺序存放在结果寄存器里面的呢?

说个简单的解释,结果寄存器的顺序是不动的,而你的1-16时可以改变顺序的,如果你的1通道的排序为1,你的结果存放在结果寄存器1,如果你的16通道排序为1,你的结果存放在结果寄存器1,结果寄存器只和你的排列顺序一一对应。

 

3 双排序方式的配置过程

双排序的工作方式下,SEQ1和SEQ2彼此独立,同时触发源也是独立的。并且SEQ1的优先级是高于SEQ2的优先级的

第一步:设置ADC时钟 ,运行模式和采样模式,一般为12.5M,非连续运行模式和顺序采样

第二步:设置双排序的工作方式

第三步:设置最大通道数

第四步:使能SEQ1中断,通过ADCCHSELSEQx来排转换顺序。

代码例子+注释: 双排序方式下的SEQ1的0-3通道和SEQ2的8-11打开操作

   AdcRegs.ADCTRL1.bit.ACQ_PS = ADC_SHCLK;  //设置ADC时钟
   AdcRegs.ADCTRL3.bit.SMODE_SEL= 1;        //设置为同步采样
   AdcRegs.ADCTRL1.bit.CONT_RUN= 0;         //设置为非连续运行方式
   AdcRegs.ADCTRL1.bit.SEQ_CASC = 0;        //设置为级联工作方式
   AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 0x3;   //设置最大通道数
   AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 0x3;   //设置最大通道数
   AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x0;   //SEQ1对应CONV00-03
   AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x1;
   AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 0x2;
   AdcRegs.ADCCHSELSEQ1.bit.CONV03 = 0x3;
 
   AdcRegs.ADCCHSELSEQ3.bit.CONV08 = 0x8;   //SEQ3对应CONV08-11
   AdcRegs.ADCCHSELSEQ3.bit.CONV09 = 0x9;
   AdcRegs.ADCCHSELSEQ3.bit.CONV10 = 0xA;
   AdcRegs.ADCCHSELSEQ3.bit.CONV11 = 0xB;


   AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 0x1;     //打开SEQ1中断
   AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1 = 0x1;   //使能 PWMA SOC触发

   AdcRegs.ADCTRL2.bit.INT_ENA_SEQ2 = 0x1;     //打开SEQ1中断
   AdcRegs.ADCTRL2.bit.EPWM_SOCB_SEQ2 = 0x1;   //使能 PWMB SOC触发
  • 26
    点赞
  • 109
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
以下是DSP28335的ADC采样中断方式获取采样值的代码: ```c #include "DSP2833x_Device.h" // 定义ADC采样结果缓存数组 Uint16 ADC_Result[16]; // ADC采样中断服务函数 interrupt void ADC_ISR(void) { Uint16 i; // 清除ADC中断标志位 ADC_clearIntFlag(ADC_INT_NUMBER1); // 读取ADC采样结果,并保存到缓存数组中 for (i = 0; i < 16; i++) { ADC_Result[i] = ADC_readResult(i); } } void main(void) { // 初始化系统时钟和GPIO InitSysCtrl(); InitGpio(); // 初始化ADC ADC_enableBandgap(ADC_ADCA); ADC_enableRefBuffers(ADC_ADCA); ADC_powerUp(ADC_ADCA); DELAY_US(1000); ADC_calibrate(ADC_ADCA); ADC_setIntMode(ADC_ADCA, ADC_INT_NUMBER1, ADC_INT_MODE_EOC); ADC_setIntSrc(ADC_ADCA, ADC_INT_NUMBER1, ADC_SOC_NUMBER0); ADC_setSocChanNumber(ADC_ADCA, ADC_SOC_NUMBER0, ADC_CH_ADCIN0); ADC_setSocTrigSrc(ADC_ADCA, ADC_SOC_NUMBER0, ADC_TRIG_EPWM1_SOCA); ADC_enableSocInt(ADC_ADCA, ADC_SOC_NUMBER0); ADC_enableInt(ADC_ADCA, ADC_INT_NUMBER1); ADC_enableContinuousMode(ADC_ADCA); ADC_startConversion(ADC_ADCA, ADC_SOC_NUMBER0); // 配置ADC中断 EALLOW; PieVectTable.ADCINT1 = &ADC_ISR; PieCtrlRegs.PIEIER1.bit.INTx1 = 1; IER |= M_INT1; EINT; // 循环等待ADC采样完成并打印结果 while (1) { // TODO: 等待ADC采样完成 // TODO: 打印ADC采样结果 } } ``` 在上面的代码中,通过`ADC_enableContinuousMode`函数使ADC进入连续采样模式,然后通过`ADC_startConversion`函数启动ADC采样,并在`ADC_ISR`中断服务函数中读取ADC采样结果,并保存到`ADC_Result`数组中。在主程序中,可以通过循环等待ADC采样完成,并通过`ADC_Result`数组获取采样结果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值