2833|0

5

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

MSP430F1232针对ADC10(使用DTC+SA)的内存中采样结果读取 [复制链接]


定义一个指针,让它指向内存的某个地址,然后通过指针就可以访问。如果需要访问地址为0x210的内存单元(MSP430的ram起始地址是0x200),则可以这样:

char a;
char *p;
p=0x210;
*p=90;//在地址为0x210的内存单元存入一个数字90
a= *p;//将地址为0x210的内存单元中的数字读出赋值给a其实不光是430单片机,其他各种单片也是如此操作,这是由C语言决定的,与具体CPU无关,但各种单片机内存的地址范围不同,这个需要注意。

==============以上内容引自“百度知道”==================

地址空间的0x0200为起始地址,往高地址增长是RAM占用的地址空间,RAM占用空间的大小跟具体的器件直接相关。RAM部分可以用来存储数据和指令。

MSP430F1232的ADC10转换结果存放在ADC10SA指定的起始地址中,地址是连续的,每个地址中存放多大的数据?ADC10转换结果先放在16位MEM中,那么这16位怎么放在内存中,怎么取出来?

第一个问题:每个地址中存放8位数据第二个问题:应该是MEM中的低八位放在sa指定的初始地址a0中,高八位放在下一个地址,也就是a0+1中,到底是不是这么放的,因为手册中并没有明确的写出来,也或者自己没有找到,所以最有效的方法是通过一个例程,单步调试程序,看一下a0和a0+1地址取出的数据到底是什么样的,这是最有效的方式,所以不要嫌麻烦。

个人感觉上述来自百度知道的方法应该是有效的,但是经过实验发现该内存读写代码无法实现读取内存的目的,经过查找别的资料,发现使用AD10的ADT+SA采样转换的内存读取方案:

MSP430的ADC10的DTC功能确实强大,它支持将ADC10MEM中的内容自动存放到任意地址。经过上面的学习,我们已经知道必须要设置ADC10SA来确认传送的目标地址,然后通过设置ADC10DTC1来确认传送的数据大小(字节数),另外还可以通过设置ADC10DTC0中的ADC10TB来选择传输一块或者两块数据、设置ADC10CT来选择是否连续传递数据。

因为大家现在还没有学习flash模块,为了避免覆盖flash中的重要数据(比如我们每次用到的CALBC1_16MHZ和CALDCO_16MHZ都是在flash中存放的),我们只在RAM中做文章。我们可以给定一个固定的地址,比如0x0200,但是我们如何保证这些地址不会被别的程序覆盖呢,确实很难保证。Cloud也不推荐用这种方式。那么我们能不能利用DTC直接将数据存放到我们的变量中呢?

答案是肯定的。学习过指针的同学都知道,在程序中,所有的变量都是有其地址的,通过这个思想,我们让ADC10SA指向某个变量的地址,然后再将ADC10DTC1的大小和变量长度相匹配就好了。




  1. #include <msp430.h>  
  2.   
  3. #define  uchar    unsigned char  
  4. #define  ushort    unsigned short  
  5.   
  6. ushort temp0, temp1;  
  7. uchar temp0_L, temp0_H;  
  8. uchar temp1_L, temp1_H;  
  9. ushort array[2] = (0);  
  10.   
  11. int main(void)  
  12. {  
  13.   WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT  
  14.   BCSCTL1 |= DIVA_2;                        // ACLK = LFXT1CLK/8  
  15.   ADC10CTL1 = ADC10SSEL_1 + INCH_1 + CONSEQ_1;            // A1/A0, single sequence, 选择ACLK作为时钟源  
  16.   ADC10CTL0 = MSC + ADC10ON + ADC10IE + REFON + REF2_5V;     //时钟源分频+连续  
  17.   ADC10DTC1 = 0x02;                         // 2 conversions  
  18.   ADC10AE |= 0x03;                          // P2.1,0 ADC10 option select  
  19.   P3SEL |= 0x30;                            // P3.4,5 = USART0 TXD/RXD  
  20.   P3DIR |= 0x10;                            // P3.4为输出  
  21.   ME2 |= UTXE0 + URXE0;                     // Enabled USART0 TXD/RXD  
  22.   UCTL0 |= CHAR;                            // 8-bit character  
  23.   UTCTL0 |= SSEL1;                          // UCLK = SMCLK, 选择SMCLK作为时钟源  
  24.   UBR00 = 0xD0;                             // 2MHz 9600  
  25.   UBR10 = 0x00;                             //  
  26.   UMCTL0 = 0x00;                            // no modulation  
  27.   UCTL0 &= ~SWRST;                          // Initalize USART state machine  
  28.   IE2 |= URXIE0;                            // Enabled USART0 RX interrupt  
  29.    
  30.   for (;;)  
  31.   {  
  32.     ADC10CTL0 &= ~ENC;  
  33.     while (ADC10CTL1 & BUSY);               // Wait if ADC10 core is active  
  34.     ADC10SA = (short) (array);                        // Data buffer start  
  35.     ADC10CTL0 |= ENC + ADC10SC;             // Sampling and conversion start  
  36.     __bis_SR_register(CPUOFF + GIE);        // LPM0, ADC10_ISR will force exit  
  37.     //AD把两路转换完成,而且给了ADC10SA控制将长度为2的数据块放到某个地址中,那么可以从地址中取出转换完成的数据  
  38.     //一个块放着两个转换完的数据,每个转换完的数据长度是2个字节,一个地址是一个字节,现在的地址是在0x200的基础上加4  
  39.     //但是这个地址是个什么意思不太明白  
  40.     //对于中断来说,当每次两个整个数据块都传递完成时,中断标志置1,此时产生中断,让CPU跳出低功耗状态,继续执行上面的for循环  
  41.     //继续开始转换,由于AD转换独立于CPU,所以CPU又进入低功耗状态,当转换完成时再次跳出低功耗,这样不断进入跳出,实现低功耗。  
  42.     //所以低功耗跳出之后,以下应该写串口传输的代码,将转换完的数字量给USART  
  43.     //很简单,模数转换之后,结果自然保存到了array数组中,数组每个元素的大小是2字节,因为ADC是10位,采样结果先放在2字节的MEM寄存器中  
  44.     //所以一次转换结果在内存中占用两个连续的地址,也就是2字节大小  
  45.     temp0_L = array[1] & 0x00ff;  
  46.     temp0_H = (array[1]>>8) & 0x00ff;  
  47.     temp1_L = array[0] & 0x00ff;  
  48.     temp1_H = (array[0]>>8) & 0x00ff;  
  49.     //array[1]对应着A0的数字输出;array[0]对应着A1的数字输出  
  50.     while (!(IFG2 & UTXIFG0));   
  51.     TXBUF0 = 0xC0;  
  52.       
  53.     while (!(IFG2 & UTXIFG0));   
  54.     TXBUF0 = temp0_H;  
  55.     while (!(IFG2 & UTXIFG0));   
  56.     TXBUF0 = temp0_L;   
  57.       
  58.     while (!(IFG2 & UTXIFG0));   
  59.     TXBUF0 = temp1_H;  
  60.     while (!(IFG2 & UTXIFG0));   
  61.     TXBUF0 = temp1_L;  
  62.       
  63.     while (!(IFG2 & UTXIFG0));   
  64.     TXBUF0 = '\n';  
  65.       
  66.   }  
  67. }  
  68.   
  69. // ADC10 interrupt service routine  
  70. #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)  
  71. #pragma vector=ADC10_VECTOR  
  72. __interrupt void ADC10_ISR (void)  
  73. #elif defined(__GNUC__)  
  74. void __attribute__ ((interrupt(ADC10_VECTOR))) ADC10_ISR (void)  
  75. #else  
  76. #error Compiler not supported!  
  77. #endif  
  78. {  
  79.     __bic_SR_register_on_exit(CPUOFF);      // Clear CPUOFF bit from 0(SR)  
  80. }  
复制代码


 
点赞 关注

回复
举报
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表