之前一篇《Objective-C的单例模式(singleton)》
http://arthurchen.blog.51cto.com/2483760/642536
介绍了创建单例的方式,不过后来发现其实在ios 4.0后有更加简单的方式。
就是使用GCD的功能
代码如下:
+ (instantClass *)sharedClient {
static instantClass *_sharedClient = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedClient = [[instantClass alloc] init];
});
return _sharedClient;
}
网上少有STM32与MPC-6050通讯的介绍,可以用的代码就更少了。辛苦了几天,终于将其调通,共享出来与大家分享。
什么都不说了,直接上代码,大家看注释就行了:
i2c.h
#ifndef __I2C_H
#define __I2C_H
#include "sys.h"
//IO方向设置
#define SDA_IN() {GPIOB->CRH&=0XFFFF0FFF;GPIOB->CRH|=8<<12;}
#define SDA_OUT() {GPIOB->CRH&=0XFFFF0FFF;GPIOB->CRH|=3<<12;}
//IO操作函数
#define IIC_SCL PBout(10) //SCL
#define IIC_SDA PBout(11) //SDA
#define READ_SDA PBin(11) //输入SDA
//IIC所有操作函数
void IIC_Init(void); //初始化IIC的IO口
void IIC_Start(void); //发送IIC开始信号
void IIC_Stop(void); //发送IIC停止信号
void IIC_Send_Byte(u8 txd); //IIC发送一个字节
u8 IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
u8 IIC_Wait_Ack(void); //IIC等待ACK信号
void IIC_Ack(void); //IIC发送ACK信号
void IIC_NAck(void); //IIC不发送ACK信号
void IIC_Write_One_Byte(u8 daddr,u8 addr,u8 data);
u8 IIC_Read_One_Byte(u8 daddr,u8 addr);
#endif
i2c.c
#include "i2c.h"
#include "delay.h"
//初始化IIC
void IIC_Init(void)
{
RCC->APB2ENR|=1<<3;//先使能外设IO PORTB时钟
GPIOB->CRH&=0XFFFF00FF;//PB10/11 推挽输出
GPIOB->CRH|=0X00003300;
GPIOB->ODR|=3<<10; //PB10/11 输出高
}
//产生IIC起始信号
void IIC_Start(void)
{
SDA_OUT(); //sda线输出
IIC_SDA=1;
IIC_SCL=1;
delay_us(5);
IIC_SDA=0;//START:when CLK is high,DATA change form high to low
delay_us(5);
IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
}
//产生IIC停止信号
void IIC_Stop(void)
{
SDA_OUT();//sda线输出
IIC_SCL=0;
IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
delay_us(5);
IIC_SCL=1;
IIC_SDA=1;//发送I2C总线结束信号
delay_us(5);
}
//等待应答信号到来
//返回值:1,接收应答失败
// 0,接收应答成功
u8 IIC_Wait_Ack(void)
{
u8 ucErrTime=0;
SDA_IN(); //SDA设置为输入
IIC_SDA=1;delay_us(5);
IIC_SCL=1;delay_us(5);
while(READ_SDA)
{
ucErrTime++;
if(ucErrTime>250)
{
IIC_Stop();
return 1;
}
}
IIC_SCL=0;//时钟输出0
return 0;
}
//产生ACK应答
void IIC_Ack(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=0;
delay_us(5);
IIC_SCL=1;
delay_us(5);
IIC_SCL=0;
}
//不产生ACK应答
void IIC_NAck(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=1;
delay_us(5);
IIC_SCL=1;
delay_us(5);
IIC_SCL=0;
}
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答
void IIC_Send_Byte(u8 txd)
{
u8 t;
SDA_OUT();
IIC_SCL=0;//拉低时钟开始数据传输
for(t=0;t<8;t++)
{
IIC_SDA=(txd&0x80)>>7;
txd<<=1;
delay_us(5); //对TEA5767这三个延时都是必须的
IIC_SCL=1;
delay_us(5);
IIC_SCL=0;
delay_us(5);
}
}
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
u8 IIC_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
SDA_IN();//SDA设置为输入
for(i=0;i<8;i++ )
{
IIC_SCL=0;
delay_us(5);
IIC_SCL=1;
receive<<=1;
if(READ_SDA)receive++;
delay_us(5);
}
if (!ack)
IIC_NAck();//发送nACK
else
IIC_Ack(); //发送ACK
return receive;
}
mpc6050.h
#ifndef __MPU6050_H #define __MPU6050_H #include "sys.h" //**************************************** // 定义MPU6050内部地址 //**************************************** #define SMPLRT_DIV 0x19 //陀螺仪采样率,典型值:0x07(125Hz) #define CONFIG 0x1A //低通滤波频率,典型值:0x06(5Hz) #define GYRO_CONFIG 0x1B //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s) #define ACCEL_CONFIG 0x1C //加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz) #define ACCEL_XOUT_H 0x3B #define ACCEL_XOUT_L 0x3C #define ACCEL_YOUT_H 0x3D #define ACCEL_YOUT_L 0x3E #define ACCEL_ZOUT_H 0x3F #define ACCEL_ZOUT_L 0x40 #define TEMP_OUT_H 0x41 #define TEMP_OUT_L 0x42 #define GYRO_XOUT_H 0x43 #define GYRO_XOUT_L 0x44 #define GYRO_YOUT_H 0x45 #define GYRO_YOUT_L 0x46 #define GYRO_ZOUT_H 0x47 #define GYRO_ZOUT_L 0x48 #define PWR_MGMT_1 0x6B //电源管理,典型值:0x00(正常启用) #define WHO_AM_I 0x75 //IIC地址寄存器(默认数值0x68,只读) #define SlaveAddress 0xD0 //IIC写入时的地址字节数据,+1为读取 #define MPU_60X0_PWR_MGMT_1_REG_ADDR 0x6B #define MPU_60X0_USER_CTRL_REG_ADDR 0x6A #define MPU_60X0_SMPLRT_DIV_REG_ADDR 0x19 #define MPU_60X0_CONFIG_REG_ADDR 0x1A #define MPU_60X0_GYRO_CONFIG_REG_ADDR 0x1B #define MPU_60X0_ACCEL_CONFIG_REG_ADDR 0x1C #define MPU_60X0_FIFO_EN_REG_ADDR 0x23 #define MPU_60X0_RESET_REG_VALU 0x80 #define MPU_60X0_PWR_MGMT_1_REG_VALU 0x09 // Disable temperature sensor, PLL with X axis gyroscope reference #define MPU_60X0_USER_CTRL_REG_VALU 0x45 // Enable FIFO. Reset FIFO and signal paths for all sensors #define MPU_60X0_SMPLRT_DIV_REG_VALU 0x00 // DLPF_CFG is 0x01, so Gyroscope Output Rate = 1kHz, divided by 1, still 1kHz #define MPU_60X0_CONFIG_REG_VALU 0x03 // 184Hz 2.0ms 188Hz 1.9ms 1kHz. So there will be 6x2 bytes new data in FIFO every 1ms #define MPU_60X0_GYRO_CONFIG_REG_VALU 0x08 // Gyroscope works at 500dps. If selftest is needed, REMEMBER to put this to 250dps #define MPU_60X0_ACCEL_CONFIG_REG_VALU 0x08 // Accelerometer works at 4g range. If selftest is needed, REMEMBER to put this to 8g range #define MPU_60X0_FIFO_EN_REG_VALU 0x78 // Only enable accel and gyro extern u16 delayTime; void Single_WriteI2C(u8 REG_Address,u8 REG_data); u8 Single_ReadI2C(u8 REG_Address); void InitMPU6050(void); u16 GetData(u8 REG_Address); void I2C1_WriteByte(u8 REG_Address,u8 REG_data); u8 I2C1_ReadByte(u8 DataAddr); void SetDelayTime(u16 delayMs); #endif
mpc6050.c
#include "delay.h"
#include "mpu6050.h"
#include "i2c.h"
u16 delayTime = 1000;
//**************************************
//向I2C设备写入一个字节数据
//**************************************
void Single_WriteI2C(u8 REG_Address,u8 REG_data)
{
IIC_Start(); //起始信号
IIC_Send_Byte(SlaveAddress); //发送设备地址+写信号
IIC_Wait_Ack();
IIC_Send_Byte(REG_Address); //内部寄存器地址,
IIC_Wait_Ack();
IIC_Send_Byte(REG_data); //内部寄存器数据,
IIC_Wait_Ack();
IIC_Stop(); //发送停止信号
}
//**************************************
//从I2C设备读取一个字节数据
//**************************************
u8 Single_ReadI2C(u8 REG_Address)
{
u8 REG_data;
IIC_Start(); //起始信号
IIC_Send_Byte(SlaveAddress); //发送设备地址+写信号
IIC_Wait_Ack();
IIC_Send_Byte(REG_Address); //发送存储单元地址,从0开始
IIC_Wait_Ack();
IIC_Start(); //起始信号
IIC_Send_Byte(SlaveAddress+1); //发送设备地址+读信号
IIC_Wait_Ack();
REG_data=IIC_Read_Byte(0); //读出寄存器数据
//IIC_SendAck(); //接收应答信号
IIC_Stop(); //停止信号
return REG_data;
}
//**************************************
//初始化MPU6050
//**************************************
void InitMPU6050()
{
/*
Single_WriteI2C(PWR_MGMT_1, 0x00); //解除休眠状态
Single_WriteI2C(SMPLRT_DIV, 0x07);
Single_WriteI2C(CONFIG, 0x06);
Single_WriteI2C(GYRO_CONFIG, 0x18);
Single_WriteI2C(ACCEL_CONFIG, 0x01);
*/
u32 i;
Single_WriteI2C(MPU_60X0_PWR_MGMT_1_REG_ADDR, MPU_60X0_RESET_REG_VALU);
for (i = 0; i < 20000; i++)
{
delay_us(5); //上电延时
}
Single_WriteI2C(MPU_60X0_PWR_MGMT_1_REG_ADDR, MPU_60X0_PWR_MGMT_1_REG_VALU);
Single_WriteI2C(MPU_60X0_USER_CTRL_REG_ADDR, MPU_60X0_USER_CTRL_REG_VALU);
Single_WriteI2C(MPU_60X0_SMPLRT_DIV_REG_ADDR, MPU_60X0_SMPLRT_DIV_REG_VALU);
Single_WriteI2C(MPU_60X0_CONFIG_REG_ADDR, MPU_60X0_CONFIG_REG_VALU);
Single_WriteI2C(MPU_60X0_GYRO_CONFIG_REG_ADDR, MPU_60X0_GYRO_CONFIG_REG_VALU);
Single_WriteI2C(MPU_60X0_ACCEL_CONFIG_REG_ADDR, MPU_60X0_ACCEL_CONFIG_REG_VALU);
Single_WriteI2C(MPU_60X0_FIFO_EN_REG_ADDR, MPU_60X0_FIFO_EN_REG_VALU);
}
//**************************************
//合成数据
//**************************************
u16 GetData(u8 REG_Address)
{
u8 H,L;
H=Single_ReadI2C(REG_Address);
L=Single_ReadI2C(REG_Address+1);
return (H<<8)+L; //合成数据
}
void SetDelayTime(u16 delayMs)
{
delayTime = delayMs;
}
Google 的千兆光纤终于在堪萨斯城开通了。对于 Google 来说,高速网络是实现其各种愿景的保证,那么,对于提前享受到高速网络的当地人来说,这意味着什么呢?Ars Technica 网站特意走访了堪萨斯城的“Homes For Hackers”。
Homes For Hackers(黑客之家)是当地网络开发者 Ben Barreth 创建的。他最初的目的是想做一个中介,在寻求居住工作地点的企业家和乐意提供场所的本地居民之间打通联系。不过,当 Google 宣布了光纤入户的时间表之后,Barreth 发现所在的街区不属于第一批开通的区域,许多人要到 2013 年夏才能获得高速网络,因为他决定自己动手。在今年 9 月的时候,他以接近五万美元的价格买下了离家不太远的一套房子。
Ben Barreth 和他的妻子无意从房子中获益。他们将其视为哺育堪萨斯新生科技社区的机会。Ben Barreth 会让企业家们在房子里免费居住三个月。他告诉 Ars 网站,他们是非常虔诚的基督徒,从其他人那里获得了许多帮助,因此想要回报社会,“从财务上说,这没有什么道理,但是我认为这会使堪萨斯受益。我们购买房 子的原因是,在堪萨斯城,没有人像我们一样真正去探索光纤的用途,这是我带动其他人探索的一种方式。”
不过,夫妻两人并不富裕。Ben Barreth 希望能够获得捐赠、赞助,或者通过 AirBnB 把卧室租给第一批的 Google 光纤旅游者。他说,如果以 50 美元一夜的价格租出房间,10 个夜晚的收入就能够补偿房屋贷款,以及多数设施的花费。
在 Google 光纤开通之后,很快就有企业家入驻了。Threedee 的创始人 Mike Demarais 刚刚在这里住下,他告诉 Ars 网站,“我们今天得以使用它,在过去的几个小时里,我一直没有离开笔记本。这是不可思议的,我可能不会离开这所房子了。”
他说,在通过网线连接的情况下,Google 光纤的速度稳定在 600 到 700Mbps。即使是较慢的无线连接,也比大多数美国家庭的网络要快多了。“我做的第一件事情就是通过 BT 下载 Ubuntu”,他说,“我感觉花了两分钟就下完了,让我现在再试试。”。
Mike Demarais 说自己很快被高速网络惯坏了,“试过这个之后,无论我去哪里,互联网速度都是一场灾难”。
他的公司是与 3D 打印相关的。“我们在开发一个前端的开发工具包,可以让开发者们在浏览器中浏览和操作 3D 模型,”他说,“我们有一个 API,可以让你把这些模型直接用 3D 打印机打印出来。”他说这个过程完全是使用网络技术的。
Demarais 说他考虑搬到这里的原因,一部分是因为 Google 光纤,一部分是因为“Home for Hackers”的条件优越,能够免租金住上三个月对他意义很大。不过,他认为堪萨斯城还需要提供自己独特的价值,“光纤是不够的。我觉得,一个密集的初 创公司群体是有必要的,如果年轻人不来这里搞初创公司,需要人工来创造那种流动”。