好资料要分享,所有贴子里的资料不收费,不隐藏。
上来先抱怨一下,刚刚费了半天劲写的贴子,点击提交的时候只给了我这么一句话,剩下就什么也没有了,对,我写的东西也没有了。
最近用MSP430FR5969做了一个飞思卡尔地磁传感器的测试。
下面是MAG3110的官方介绍:
MAG3110是一款小型低功耗数字3-D磁传感器,具有较宽的动态范围,能够在外部磁场较高的PCB中工作。MAG3110
磁力计可以测量局部磁场的3个分量,这些分量就是地磁场与电路板中组件产生的磁场之和。
与 3轴加速度传感器结合使用时,可以获得独立于方向的精确罗盘方位信息。MAG3110采用标准I2C串行接口,能
够测量最高10高斯的局部磁场,输出数据 速率(ODR)高达80 Hz。这些输出数据速率对应的采样间隔从12 ms至数
秒不等。MAG3110采用塑料DFN封装,在-40°C至+85°C宽温度范围能够可靠工作。
特性
最大采样率80 Hz
400 kHz I2C接口
工作温度-40°C至+85°C
工作电压0.95至3.6V
因为考虑到以后做FR5969项目时的引脚灵活性,我使用了I/O口I模拟I2C,这样的好处是灵活,坏处是费电,占用cpu资源。
以前一直喜欢用硬件外设,430的用过一些单片机,I2C部分感觉硬件的代码看起来不是很爽,也比较难使用。
我在网上抄了一个软I2C的代码(太简单懒的写),然后做了一些修改,(这里的延时函数不准,因为和时钟频率有关不要拿来直接使用):
- /*******************************************************************************
- * Copyright (C), 2014, ?? ??. Co., Ltd.
- * FileName: soft_i2c.c
- * Author: littleshrimp
- * Version : 1.0
- * Date: 2014-10-3 13:16
- * Description:
- * Function List: //
- * 1. -------
- * History:
- * <author> <time> <version > <desc>
- * littleshrimp 2014-10-3 13:16 1.0 build this moudle
- ******************************************************************************/
- /*******************************************************************************
- * * INCLUDES
- * */
- #include <msp430.h>
- #include "soft_i2c.h"
- /*******************************************************************************
- * * MACROS
- * */
- /*******************************************************************************
- * * CONSTANTS
- * */
- /*******************************************************************************
- * * TYPEDEFS
- * */
- /*******************************************************************************
- * * GLOBAL VARIABLES
- * */
- /*******************************************************************************
- * * EXTERNAL VARIABLES
- * */
- /*******************************************************************************
- * * EXTERNAL FUNCTIONS
- * */
- /*******************************************************************************
- * * LOCAL VARIABLES
- * */
- /*******************************************************************************
- * * PROFILE CALLBACKS
- * */
- /*******************************************************************************
- * * LOCAL FUNCTIONS
- * */
- /*******************************************************************************
- * * PUBLIC FUNCTIONS
- * */
- /*******************************************************************************
- * Function: delay_ms
- * Description: 延时一毫秒
- * Calls:
- * Input: unsigned char time
- * Return: void
- ******************************************************************************/
- void delay_ms(unsigned char time)
- {
- while( time --)
- {
- __delay_cycles(60);
- }
- }
- /*******************************************************************************
- * Function: delay_us
- * Description: 延时一微秒
- * Calls:
- * Return: void
- ******************************************************************************/
- void delay_us()
- {
- __delay_cycles(6);
- }
- /*******************************************************************************
- * Function: start
- * Description: 起始位
- * Calls:
- * Return: void
- ******************************************************************************/
- void start()
- {
- SET_SDA_OUT;
- SDA_HIGH;
- delay_us();
- SCL_HIGH;
- delay_us();
- SDA_LOW;
- delay_us();
- SCL_LOW;
- delay_us();
- }
- /*******************************************************************************
- * Function: stop
- * Description: 停止位
- * Calls:
- * Return: void
- ******************************************************************************/
- void stop()
- {
- SET_SDA_OUT;
- SCL_LOW;
- delay_us();
- SDA_LOW;
- delay_us();
- SCL_HIGH;
- delay_us();
- SDA_HIGH;
- delay_ms(10);
- }
- /*******************************************************************************
- * Function: i2c_init
- * Description: 初始化I2C引脚
- * Calls:
- * Return: void
- ******************************************************************************/
- void i2c_init()
- {
- I2C_DIR|=I2C_SCL;
- I2C_DIR&=~I2C_SDA;
- SCL_LOW;
- stop();
- }
- /*******************************************************************************
- * Function: ack
- * Description: 应答标志
- * Calls:
- * Return: void
- ******************************************************************************/
- void ack()
- {
- SET_SDA_OUT;
- SDA_LOW;
- delay_us();
- SCL_HIGH;
- delay_us();
- SCL_LOW;
- delay_us();
- SDA_HIGH;
- }
- /*******************************************************************************
- * Function: noAck
- * Description: NO ACK
- * Calls:
- * Return: void
- ******************************************************************************/
- void noAck()
- {
- SET_SDA_OUT;
- SDA_HIGH;
- delay_us();
- SCL_HIGH;
- delay_us();
- SCL_LOW;
- delay_us();
- }
- /*******************************************************************************
- * Function: read_ack
- * Description: 读ACK
- * Calls:
- * Return: unsigned char
- ******************************************************************************/
- unsigned char read_ack()
- {
- unsigned char ack;
- SCL_HIGH;
- delay_us();
- SET_SDA_IN;
- delay_us();
- ack=SDA_IN;
- delay_us();
- SCL_LOW;
- delay_us();
- return(ack);
- }
- /*******************************************************************************
- * Function: write_byte
- * Description: 写一个字节
- * Calls:
- * Input: unsigned char input
- * Return: void
- ******************************************************************************/
- void write_byte(unsigned char b)
- {
- unsigned char t,t1;
- SET_SDA_OUT;
- for(t=8;t!=0;t--)
- {
- t1=b&0x80;
- if(t1==0x80)
- SDA_HIGH;
- else
- SDA_LOW;
- delay_us();
- SCL_HIGH;
- delay_us();
- SCL_LOW;
- b=b<<1;
- }
- SDA_LOW;
- }
- /*******************************************************************************
- * Function: read_byte
- * Description: 读一个字节
- * Calls:
- * Return: unsigned char
- ******************************************************************************/
- unsigned char read_byte()
- {
- unsigned char t,t1,b=0;
- SET_SDA_IN;
- for(t = 8; t != 0; t--)
- {
- SCL_HIGH;
- delay_us();
- b = b<<1;
- SET_SDA_IN;
- t1 = SDA_IN;
- if(t1 == I2C_SDA)
- b = b|0x01;
- delay_us();
- SCL_LOW;
- delay_us();
- }
- return(b);
- }
- /*******************************************************************************
- * Function: i2c_read_n_byte
- * Description: 读N个字节
- * Calls:
- * Input: unsigned char deviceAddr//设备地址,8位格式
- * Input: unsigned char dataAddr//寄存器地址
- * Input: unsigned char * data//数据
- * Input: unsigned char len//长度
- * Return: unsigned char
- ******************************************************************************/
- unsigned char i2c_read_n_byte(unsigned char deviceAddr, unsigned char dataAddr, unsigned char
- *data,unsigned char len)
- {
- start();
- write_byte(deviceAddr);//发设备地址,写
- delay_us();
- if(read_ack()==1)
- return 0;
- write_byte(dataAddr);//发寄存器地址
- delay_us();
- if(read_ack()==1)
- return 0;
- stop();
- delay_us();
- start();
- write_byte(deviceAddr | 1);//发设备地址,读
- delay_us();
- if(read_ack() == 1)
- return 0;
- while(len != 1)
- {
- *data=read_byte();
- ack();
- data++;
- len--;
- }
- *data=read_byte(); //读入最后一个字节
- noAck();
- stop();
- return 1;
- }
- /*******************************************************************************
- * Function: i2c_write_n_byte
- * Description: 写N个字节
- * Calls:
- * Input: unsigned char deviceAddr//设备地址8位
- * Input: unsigned char dataAddr//寄存器地址
- * Input: unsigned char * data//数据
- * Input: unsigned char len//长度
- * Return: unsigned char
- ******************************************************************************/
- unsigned char i2c_write_n_byte(unsigned char deviceAddr, unsigned char dataAddr, unsigned char
- *data,unsigned char len)
- {
- start();
- write_byte(deviceAddr);
- delay_us();
- if(read_ack()==1)
- return 0;
- write_byte(dataAddr);
- delay_us();
- if(read_ack()==1)
- return 0;
- for(;len > 0;len--)
- {
- write_byte(*data);
- delay_us();
- if(read_ack()==1)
- return 0;
- data++;
- }
- stop();
- return 1;
- }
复制代码
I2C调通以后接着写MAG3110的代码,这个代码也是抄的,做了一些修改:
- /*******************************************************************************
- * Function: mag3110_init
- * Description: MAG3110初始化
- * Calls:
- * Return: void
- ******************************************************************************/
- void mag3110_init()
- {
- uint8_t buf[1];
- i2c_init();//初始化I2C
- buf[0] = (BIT7|BIT6|BIT5|BIT0);
- i2c_write_n_byte(SLV_ADDR,CTRL_REG1,buf,1); //配置寄存器CTRL_REG1
- buf[0] = (BIT7|BIT4);
- i2c_write_n_byte(SLV_ADDR,CTRL_REG2,buf,1); //配置寄存器CTRL_REG2
- }
复制代码
配置完寄存器先读一下MAG3110的WHO_AM_I寄存器,地址是0x08,看看通信能否成功,如果返回0xC4说明通信正常
。
- i2c_read_n_byte(0x1c,WHO_AM_I,buf,1);//读WHO_AM_I
复制代码
确定通信正常后再读取寄存器DR_STATUS,等待数据准备完成后再读取相应通道的数据,下边是读取X通道的代码
:
- int read_x (void)
- {
- while((read_1_byte(DR_STATUS)&DR_STATUS_XDR) != DR_STATUS_XDR)//等待数据准备完毕
- {
- delay_ms(10);
- }
- return read_2_byte(OUT_X_MSB);
- }
复制代码
能正确读取到数据以后,再次数据转换成字符串,通过串口发送给PC
- sprintf(outBuf,"x:%d,y:%d,z:%d",x,y,z);
- sleep(100);
- uart_tx_string(outBuf);//输出到PC
复制代码
上边的sleep函数是使用定时器来实现的,和delay不同之处在于sleep延时期间CPU处于休眠状态,目的只有一个
,省电。
代码是TI触摸传感器库里的,基本没做什么修改,下边的延时函数的代码:
- /*******************************************************************************
- * Copyright (C), 2014, ?? Tech. Co., Ltd.
- * FileName: timer.c
- * Author: litleshrimp
- * Version : 1.0
- * Date: 2014-10-12 14:55
- * Description:
- * Function List: //
- * 1. -------
- * History:
- * <author> <time> <version > <desc>
- * litleshrimp 2014-10-12 14:55 1.0 build this moudle
- ******************************************************************************/
- /*******************************************************************************
- * * INCLUDES
- * */
- #include "msp430.h"
- /*******************************************************************************
- * * MACROS
- * */
- /*******************************************************************************
- * * CONSTANTS
- * */
- /*******************************************************************************
- * * TYPEDEFS
- * */
- /*******************************************************************************
- * * GLOBAL VARIABLES
- * */
- /*******************************************************************************
- * * EXTERNAL VARIABLES
- * */
- /*******************************************************************************
- * * EXTERNAL FUNCTIONS
- * */
- /*******************************************************************************
- * * LOCAL VARIABLES
- * */
- /*******************************************************************************
- * * PROFILE CALLBACKS
- * */
- /*******************************************************************************
- * * LOCAL FUNCTIONS
- * */
- /*******************************************************************************
- * * PUBLIC FUNCTIONS
- * */
- // Sleep Function
- // Configures Timer A to run off ACLK, count in UP mode, places the CPU in LPM3
- // and enables the interrupt vector to jump to ISR upon timeout
- void sleep(unsigned int time)
- {
- TA0CCR0 = time;
- TA0CTL = TASSEL__ACLK + MC__UP + TACLR;
- TA0CCTL0 &= ~CCIFG;
- TA0CCTL0 = CCIE;
- __bis_SR_register(LPM3_bits+GIE);
- __no_operation();
- }
- /******************************************************************************/
- // Timer0_A0 Interrupt Service Routine: Disables the timer and exists LPM3
- /******************************************************************************/
- #pragma vector=TIMER0_A0_VECTOR
- __interrupt void ISR_Timer0_A0(void)
- {
- TA0CTL &= ~(MC_1);
- TA0CCTL0 &= ~(CCIE);
- __bic_SR_register_on_exit(LPM3_bits+GIE);
- }
复制代码
串口发送程序是我通过MSP430FR5969的官方例程修改来的,因为没用到接收,也就没实现接收部分,代码里有一处问题,一直没抽出时间去解决,就是串口发送完判断后如果判断数据发送完再后马上发送下一条数据就会出问题,后来我在里边加了一个延时临时解决了:
代码写好后下到单片机里,打开串口助后就会看到数据被发送到电脑。
下边是引脚连接关系图
实物连接图:
下边是简单录制的视频(背景很吵杂,容易伤到耳朵,建议把电脑静音观看)
最后附上源代码:
ti.mcu.msp430.msp430fr5969.code.freescale.sensor.mag3110.code @19.msp430fr5969 i.rar
(746.72 KB, 下载次数: 154)
这是第一步,后续再放上带图形界面的程序。