2661|1

2781

帖子

419

TA的资源

五彩晶圆(中级)

楼主
 

msp430单片机模拟IIC总线读取MMA7660三轴加速度传感器 [复制链接]

搞了几天的msp430单片机,发现它的硬件IIC并不是很好用(没调出来,嘿嘿),所以就弃之不用了,改用模拟IIC总线的协议。用来读取MMA7660三轴加速度按传感器的X,Y,Z的值,并通过串口显示出来,串口也是通过定时器TimerA模拟来的,只是为了练习一下单片机的编程所以都用了模拟。测试结果如下:   
代码如下:
file1 :
  1. main.c
  2. #include "msp430G2452.h"
  3. #include "g2452uart.h"               
  4. #include "MMA7660FC.h"
  5. #define SDA_DirOut  P2DIR |= BIT0
  6. #define SDA_DirIn  P2DIR &=~ BIT0

  7. #define SDA_0   P2OUT &=~ BIT0
  8. #define SDA_1   P2OUT |= BIT0

  9. #define SCL_1   P2OUT |= BIT1
  10. #define SCL_0   P2OUT &=~ BIT1

  11. #define Get_Bit( x,y)  ((x&(1<<y))==0? 0="" :="" 1="" )
  12. #define SDA_in    Get_Bit(P2IN,0)

  13. char X_value=0 ;
  14. char Y_value=0 ;
  15. char Z_value=0 ;
  16. signed char  X_value_final,Y_value_final,Z_value_final;   //三轴加速度的最终值,有正负

  17. void OSC_Init()
  18. {
  19. WDTCTL=WDTPW+WDTHOLD;//close whatchdog

  20. if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF)
  21. {
  22.    while(1);                               // If calibration constants erased
  23.                                            // do not load, trap CPU!!
  24. }
  25. //1Mhz
  26. BCSCTL1 = CALBC1_1MHZ;                    // Set range
  27. DCOCTL = CALDCO_1MHZ;                     // Set DCO step + modulation */



  28. }

  29. void Port_Init()
  30. {
  31. P2DIR |= BIT0+BIT1;
  32. SDA_1;
  33. SCL_1;
  34. }
  35. void delay_us( unsigned int k )
  36. {
  37. while(k--)
  38. _nop();

  39. }

  40. void IIC_Start()
  41. {
  42. SDA_1;
  43. SCL_1;
  44. delay_us(5);
  45. SDA_0;                 //产生下降沿
  46. delay_us(5);

  47. SCL_0;                 //拉低时钟线,准备发送或者接收数据

  48. }

  49. void IIC_Stop()
  50. {
  51. SCL_1;
  52. SDA_0;
  53. delay_us(5);
  54. SDA_1;               //产生一个上升沿
  55. delay_us(5);

  56. }

  57. void IIC_SendAck()
  58. {
  59. SDA_0;
  60. SCL_1;
  61. delay_us(5);
  62. SCL_0;
  63. delay_us(5);

  64. }

  65. void IIC_SendNAck()
  66. {
  67.     SDA_1;
  68. SCL_1;
  69. delay_us(5);
  70. SCL_0;
  71. delay_us(5);
  72. }

  73. unsigned char  IIC_RecAck()
  74. {
  75. unsigned char CY ;
  76. SDA_DirIn;                //在接收模式下,设置SDA的方向为输入
  77.      SCL_1;                    //拉高时钟线
  78.     delay_us(5);                 //延时
  79.     CY = SDA_in;                   //读应答信号
  80.     SCL_0 ;                    //拉低时钟线
  81.     delay_us(5);                 //延时
  82.     SDA_DirOut;                //接收结束的时候还要吧SDA的方向切换过来
  83.     return CY;



  84. }

  85. void IIC_WriteByte(unsigned int  data)
  86. {
  87.   unsigned char i ;
  88.   for (i=0;i<8;i++)
  89.   {

  90. if((data&0x80)?1:0)  //分别发送每一位二进制数据
  91. SDA_1;
  92. else
  93. SDA_0 ;

  94. SCL_1;
  95. data<<=1;           //移位传送下一位
  96. delay_us(5);
  97. SCL_0;               //在SCL上升沿的时候加载一位的数据
  98. delay_us (5);
  99.   }
  100.   SDA_1; //8位数据位发送完释放数据总线,同时SDA拉高
  101. // IIC_Recevie();  //接收答信号

  102. }
  103. unsigned char  IIC_Read(void )
  104. {

  105. unsigned char i ,data=0;
  106. SDA_DirIn;                //在接收模式下,设置SDA的方向为输入
  107. for (i=0;i<8;i++)
  108. {
  109. SCL_0;
  110. delay_us(5);
  111. SCL_1 ;                //SCL下降沿期间有数据,当SCL为高时数据线上的数据才有效
  112. data<<=1;
  113. data|=SDA_in;
  114. delay_us(3);
  115. }
  116. SDA_DirOut;                //接收结束的时候还要吧SDA的方向切换过来
  117. return data;

  118. }

  119. void WriteToAddr(unsigned char REG_addr, unsigned char REG_data )
  120. {

  121. IIC_Start();
  122.   IIC_WriteByte(SlaveAddress+0);           //发送从机地址+写入操作0
  123.   IIC_RecAck();                  //应答

  124.   IIC_WriteByte(REG_addr);        //写入内部寄存器地址
  125.   IIC_WriteByte(REG_data);        //写入内部寄存器数据
  126.   IIC_RecAck();
  127.   IIC_Stop();
  128.   delay_us(5);
  129. }
  130. unsigned char ReadFromAddr(unsigned char REG_addr)
  131. {

  132. unsigned char RecData ;
  133. IIC_Start();                  //启动IIC总线
  134. IIC_WriteByte(SlaveAddress+0);   //写入从机地址+写命令0
  135. IIC_WriteByte(REG_addr);     //写入要读的内部寄存器地址

  136. IIC_Start();
  137. IIC_WriteByte(SlaveAddress+1);   //写入从机地址+读命令1
  138. RecData=IIC_Read();
  139. IIC_SendNAck();
  140. IIC_Stop();
  141. return RecData;

  142. }
  143. void MMA7660_Init()
  144. {
  145. WriteToAddr(MMA7660_MODE,0x01);

  146. }
  147. void Read3axle(void)
  148. {

  149. X_value=ReadFromAddr(X_outAddr);
  150. Y_value=ReadFromAddr(Y_outAddr);
  151. Z_value=ReadFromAddr(X_outAddr);

  152. //将采集到的数据转换到-32~31之间
  153.      X_value_final=(char)(X_value<<2);
  154.      X_value_final =(char)(X_value_final /4);

  155.      Y_value_final= (char)(Y_value<<2);
  156.      Y_value_final = (char)(Y_value_final /4);

  157.      Z_value_final= (char)(Z_value<<2);
  158.      Z_value_final = (char)(Z_value_final /4);

  159. }

  160. //-----------主函数-----------------------------------------------------------
  161. void main(void)
  162. {
  163. OSC_Init();
  164. Port_Init();
  165. TimerA_UART_init();
  166. MMA7660_Init();
  167. __enable_interrupt();

  168. TimerA_UART_print("All Initialization is OK!");

  169. for (;;)
  170. {
  171. //__bis_SR_register(LPM0_bits);
  172. Read3axle();
  173. if (X_value_final>0)
  174. P1OUT|= BIT0;
  175. else if(X_value_final<0)
  176. P1OUT&=~ BIT0;
  177. else _nop();

  178. //------------------------------
  179. TimerA_UART_print("X_value---->");
  180. output((unsigned int )X_value,4);
  181. TimerA_UART_print("    ");
  182. //------------------------------
  183.     TimerA_UART_print("Y_value---->");
  184. output((unsigned int )Y_value,4);
  185. TimerA_UART_print("    ");
  186. //------------------------------
  187. TimerA_UART_print("Z_value---->");
  188. output((unsigned int )Z_value,4);
  189. TimerA_UART_print("");
  190. //------------------------------


  191. P1OUT ^= BIT6 ;
  192. //delay_us(20000);

  193. }

  194. }
  195. //-------------------华丽的分割线-----------------------------------------------------------------
  196. //file2 : g2452uart.h

  197. #include "msp430g2452.h"

  198. //------------------------------------------------------------------------------
  199. // Hardware-related definitions
  200. //------------------------------------------------------------------------------
  201. #define UART_TXD   0x02                     // TXD on P1.1 (Timer0_A.OUT0)
  202. #define UART_RXD   0x04                     // RXD on P1.2 (Timer0_A.CCI1A)

  203. //------------------------------------------------------------------------------
  204. // Conditions for 9600 Baud SW UART, SMCLK = 1MHz
  205. //------------------------------------------------------------------------------
  206. #define UART_TBIT_DIV_2     (1000000 / (9600 * 2))
  207. #define UART_TBIT           (1000000 / 9600)

  208. //------------------------------------------------------------------------------
  209. // Global variables used for full-duplex UART communication
  210. //------------------------------------------------------------------------------
  211. unsigned int txData;                        // UART internal variable for TX
  212. unsigned char rxBuffer;                     // Received UART character

  213. //------------------------------------------------------------------------------

  214. // 串口通信的接口函数说明:
  215. //------------------------------------------------------------------------------
  216. void TimerA_UART_init(void);
  217. //TimerA_UART_init()模拟串口通信初始化函数,在main()函数中调用此函数就可以使用一下两个函数了

  218. void TimerA_UART_tx(unsigned char byte);
  219. //TimerA_UART_tx( byte ) 通过串口发送一字节的数据

  220. void TimerA_UART_print(char *string);
  221. //TimerA_UART_print(*string) 通过串口发送任意字节的字符穿

  222. void output(unsigned int num , int n );
  223. //输出一个数字

  224. //注:接收的一字节数据存在rxBuffer变量里。

  225. void Port1_Init()
  226. {
  227.     P1OUT = 0x00;                           // Initialize all GPIO
  228.     P1SEL = UART_TXD + UART_RXD;            // Timer function for TXD/RXD pins
  229.   //  P1DIR = 0xFF & ~UART_RXD;               // Set all pins but RXD to output
  230.     //设置TXD为输出模式,P1.1和P1.2两个调试小灯也为输出模式。RXD为输入模式。
  231.     P1DIR |= UART_TXD+BIT0+BIT6;
  232.     P1DIR &=~ UART_RXD;

  233.     P1OUT &=~ BIT0+BIT6 ; //初始化让两个灯都灭。

  234.   
  235. }
  236. //------------------------------------------------------------------------------
  237. // Function configures Timer_A for full-duplex UART operation
  238. //------------------------------------------------------------------------------
  239. void TimerA_UART_init(void)
  240. {
  241. Port1_Init();                           //P1端口初始化!
  242.     TACCTL0 = OUT;                          // Set TXD Idle as Mark = '1'
  243.     TACCTL1 = SCS + CM1 + CAP + CCIE;       // Sync, Neg Edge, Capture, Int
  244.     TACTL = TASSEL_2 + MC_2;                // SMCLK, start in continuous mode
  245. }
  246. //------------------------------------------------------------------------------
  247. // Outputs one byte using the Timer_A UART
  248. //------------------------------------------------------------------------------
  249. void TimerA_UART_tx(unsigned char byte)
  250. {
  251.     while (TACCTL0 & CCIE);                 // Ensure last char got TX'd
  252.     TACCR0 = TAR;                           // Current state of TA counter
  253.     TACCR0 += UART_TBIT;                    // One bit time till first bit
  254.     TACCTL0 = OUTMOD0 + CCIE;               // Set TXD on EQU0, Int
  255.     txData = byte;                          // Load global variable
  256.     txData |= 0x100;                        // Add mark stop bit to TXData
  257.     txData <<= 1;                           // Add space start bit
  258. }

  259. //------------------------------------------------------------------------------
  260. // Prints a string over using the Timer_A UART
  261. //------------------------------------------------------------------------------
  262. void TimerA_UART_print(char *string)
  263. {
  264.     while (*string) {
  265.         TimerA_UART_tx(*string++);
  266.     }
  267. }

  268. void output(unsigned int num , int n )
  269. {
  270. char *p,pd[4];
  271.   p=pd;

  272.     pd[0]=num/1000 +48 ;  //千位
  273.     pd[1]=num/100 +48 ;// 百位
  274.     pd[2]=num0/10  +48 ; //十位
  275.     pd[3]=num   +48;//个位

  276. while (n--)
  277. TimerA_UART_tx((*p++));

  278. }
  279. //------------------------------------------------------------------------------
  280. // Timer_A UART - Transmit Interrupt Handler
  281. //------------------------------------------------------------------------------
  282. #pragma vector = TIMER0_A0_VECTOR
  283. __interrupt void Timer_A0_ISR(void)
  284. {
  285.     static unsigned char txBitCnt = 10;

  286.     TACCR0 += UART_TBIT;                    // Add Offset to CCRx
  287.     if (txBitCnt == 0) {                    // All bits TXed?
  288.         TACCTL0 &= ~CCIE;                   // All bits TXed, disable interrupt
  289.         txBitCnt = 10;                      // Re-load bit counter
  290.     }
  291.     else {
  292.         if (txData & 0x01) {
  293.           TACCTL0 &= ~OUTMOD2;              // TX Mark '1'
  294.         }
  295.         else {
  296.           TACCTL0 |= OUTMOD2;               // TX Space '0'
  297.         }
  298.         txData >>= 1;
  299.         txBitCnt--;
  300.     }
  301. }      
  302. //------------------------------------------------------------------------------
  303. // Timer_A UART - Receive Interrupt Handler
  304. //------------------------------------------------------------------------------
  305. #pragma vector = TIMER0_A1_VECTOR
  306. __interrupt void Timer_A1_ISR(void)
  307. {
  308.     static unsigned char rxBitCnt = 8;
  309.     static unsigned char rxData = 0;

  310.     switch (__even_in_range(TA0IV, TA0IV_TAIFG)) { // Use calculated branching
  311.         case TA0IV_TACCR1:                        // TACCR1 CCIFG - UART RX
  312.             TACCR1 += UART_TBIT;                 // Add Offset to CCRx
  313.             if (TACCTL1 & CAP) {                 // Capture mode = start bit edge
  314.                 TACCTL1 &= ~CAP;                 // Switch capture to compare mode
  315.                 TACCR1 += UART_TBIT_DIV_2;       // Point CCRx to middle of D0
  316.             }
  317.             else {
  318.                 rxData >>= 1;
  319.                 if (TACCTL1 & SCCI) {            // Get bit waiting in receive latch
  320.                     rxData |= 0x80;
  321.                 }
  322.                 rxBitCnt--;
  323.                 if (rxBitCnt == 0) {             // All bits RXed?
  324.                     rxBuffer = rxData;           // Store in global variable
  325.                     rxBitCnt = 8;                // Re-load bit counter
  326.                     TACCTL1 |= CAP;              // Switch compare to capture mode
  327.                     //__bic_SR_register_on_exit(LPM0_bits);  // Clear LPM0 bits from 0(SR)
  328.                 }
  329.             }
  330.             break;
  331.     }
  332. }
  333. //----------------------华丽的分割线2--------------------------------------------------------
  334. //file :MMA7660FC.h

  335. #ifndef _MMA7660FC_H
  336. #define _MMA7660FC_H

  337. #define MMA7660FC_ADD   0x4C    //Please contact the factory to request a different IIC address

  338. #define MMA7660FC_MW_ADD 0x98       //master write address
  339. #define MMA7660FC_MR_ADD 0x99       //master read address

  340. #define SlaveAddress 0x98    //从机地址
  341. #define X_outAddr  0x00
  342. #define Y_outAddr   0x01
  343. #define Z_outAddr   0x02



  344. // IIC Register Address
  345. #define MMA7660_XOUT    0x00
  346. #define MMA7660_YOUT    0x01
  347. #define MMA7660_ZOUT    0x02
  348. #define MMA7660_TILT    0x03
  349. #define MMA7660_SRST    0x04
  350. #define MMA7660_SPCNT   0x05
  351. #define MMA7660_INTSU   0x06
  352. #define MMA7660_MODE    0x07
  353. #define MMA7660_SR      0x08
  354. #define MMA7660_PDET    0x09
  355. #define MMA7660_PD      0x0A

  356. #endif

  357. ////////////////////////////////////////////////////////////////////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  358. //以上为所有程序源码!编译工具CCS V5.0
复制代码






最新回复

本帖最后由 ilovin 于 2014-7-3 10:32 编辑 ccs编译的时候     CY = SDA_in;                   //读应答信号 这句话报错 #29 expected an expression         Description        Resource        Path        Location        Type #138 expression must be a modifiable C/C++ Problem 还是把 #define Get_Bit(x,y)  ((x&(1<<y))==0? 0="" :="" 1="" ) #define SDA_in    Get_Bit(P4IN,1)复制代码 这段代码写成子函数吧!   详情 回复 发表于 2014-7-3 10:30
 
点赞 关注(2)
个人签名

回复
举报

2

帖子

0

TA的资源

一粒金砂(中级)

沙发
 
本帖最后由 ilovin 于 2014-7-3 10:32 编辑

ccs编译的时候
    CY = SDA_in;                   //读应答信号
这句话报错
#29 expected an expression        
Description        Resource        Path        Location        Type
#138 expression must be a modifiable C/C++ Problem

还是把
  1. #define Get_Bit(x,y)  ((x&(1<<y))==0? 0="" :="" 1="" )
  2. #define SDA_in    Get_Bit(P4IN,1)
复制代码

这段代码写成子函数吧!
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

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

 
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
快速回复 返回顶部 返回列表