cc2530实现i2c数据线
来源:互联网 发布:抖音为什么网络不给力 编辑:程序博客网 时间:2024/04/30 02:37
本帖最后由 L.fish 于 2010-7-29 15:47 编辑
由于英明神武的老板决定用ZigBee来做传输
结果就跑出了一些列的问题
其中一个就是MXC6202加速度传感器传输的数据用到了IIC协议
要用CC2430来做IIC的模拟
因为摸过了一段时间的CC2430,知道其中还是51的内核
以为是很简单的东西,应该和atmel的8051差不多的
但是做的时候又碰到了一系列的问题
最后绕了一圈才发现,哦,原来如此
2430芯片和51其中一个很大的区别就是:
必须人为的设置IO口的输入输出方向
也就是要设置每个端口的pin脚的PXDIR是1还是0
说还是太空泛了,那就上程序吧......
和51的程序相比,其实大部分还是相同的,我在这里就主要讲解一下两者不同的地方
只能算作一个平台的移植吧....
源程序会附在后面
SDA和SCL的读写
其实IIC总线协议的实现就是控制这两根线,让数据在规定的时候进行传输
其中就要最主要的就是对SCL的写操作和SDA的读写
以下是i2c_1.c的源程序,讲解就穿插其中.....
//i2c_1.c
#include "ioCC2430.h"
#include "i2c.h"
#define TRUE 1
#define FALSE 0
/*我的管脚定义是
SDA定义为P1.5
SCL定义为P1.4 */
#define SCL P1_4
#define SDA P1_5
/*
一个nop就是一条机器指令周期 = 1/32MHz
那32个nop就是1us啦
----这里是outman给我做出的讲解,在此再作感谢
*/
void Delay_1u(unsigned int microSecs) {
while(microSecs--)
{
/* 32 NOPs == 1 usecs */
asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
asm("nop"); asm("nop");
}
}
unsigned char error; /*错误提示,全局变量*/
/*
当通过CC2430的IO端口往外面写数据的时候
必须将对应的IO端口数据方向设置为输出
CC2430中DIRPX_Y为1时IO口为输出功能
DIRPX_Y为0时IO口为输入功能
我的SDA是P1.5,则SDA为输出功能时
P1口DIR应该是0010 0000
即0x20,其他可以依次类推......
啰嗦完毕,继续程序....
*/
void WriteSDA1(void)//SDA 输出1,相当于51里面的SDA=1 {
P1DIR |= 0x20;
SDA = 1;
}
void WriteSDA0(void)//SDA 输出0 {
P1DIR |= 0x20;
SDA = 0;
}
void WriteSCL1(void)//SCL 输出1 {
P1DIR |= 0x10;
SCL = 1;
}
void WriteSCL0(void)//SCL 输出1 {
P1DIR |= 0x10;
SCL = 0;
}
void ReadSDA(void)//这里设置SDA对应IO口DIR可以接收数据 {
P1DIR &= 0xDF;
}
/*启动I2C总线的函数,当SCL为高电平时使SDA产生一个负跳变*/
void I2C_Start_1(void)
{
WriteSDA1();
WriteSCL1();
Delay_1u(50);
WriteSDA0();
Delay_1u(50);
WriteSCL0();
Delay_1u(50);
}
/*终止I2C总线,当SCL为高电平时使SDA产生一个正跳变*/
void I2C_Stop_1(void)
{
WriteSDA0();
Delay_1u(50);
WriteSCL1();
Delay_1u(50);
WriteSDA1();
Delay_1u(50);
WriteSCL0();
Delay_1u(50);
}
/*发送0,在SCL为高电平时使SDA信号为低*/
void SEND_0_1(void) /* SEND ACK */
{
WriteSDA0();
WriteSCL1();
Delay_1u(50);
WriteSCL0();
Delay_1u(50);
}
/*发送1,在SCL为高电平时使SDA信号为高*/
void SEND_1_1(void)
{
WriteSDA1();
WriteSCL1();
Delay_1u(50);
WriteSCL0();
Delay_1u(50);
}
/*发送完一个字节后检验设备的应答信号*/
char Check_Acknowledge_1(void)
{
WriteSDA1();
WriteSCL1();
Delay_1u(50);
F0=SDA;
Delay_1u(50);
WriteSCL0();
Delay_1u(50);
if(F0==1)
return FALSE;
return TRUE;
}
void Write_Acknowledge_1(void)
{
WriteSDA0();
Delay_1u(50);
WriteSCL1();
Delay_1u(50);
WriteSCL0();
Delay_1u(50);
}
/*向I2C总线写一个字节*/
void WriteI2CByte_1(char b)
{
char i;
for(i=0;i<8;i++)
{
if((b<<i)&0x80)
{
SEND_1_1();
}
else
{
SEND_0_1();
}
}
}
/*从I2C总线读一个字节*/
char ReadI2CByte_1(void)
{
char b=0,i;
WriteSDA1();
for(i=0;i<8;i++)
{
WriteSCL0();
Delay_1u(50);
WriteSCL1();
Delay_1u(50);
ReadSDA();
F0=SDA;//寄存器中的一位,用于存储SDA中的一位数据
if(F0==1)
{
b=b<<1;
b=b|0x01;
}
else
b=b<<1;
}
WriteSCL0();
return b;
}
PS:
这里没有重要讲解IIC的实现原理
比如什么时候发送1,什么时候发送0
这里主要是讲解了一下在移植过程中需要注意的问题
如果有什么问题再问吧
整理一下需要注意的:
1.需要手动设置IO方向
2.延时设定的方式和晶振是有关系的,需要多长时间可以参照前面的程序
程序参考过robin's evolution的那篇用cc2430读取AT24CXX的驱动程序文章
以及感谢群里的on the way给我耐心讲解51的IIC
最后还是要感谢一下outman,谢谢你的提醒
over
本人尊重原文作者,这篇文章非本人原创,feibit论坛是个不错的论坛,希望大家多看看这个网站。
[注:本文源自www.feibit.com--“飞比”Zigbee论坛,如需转载请保留此行]
近来为了做一个加速度传感器的项目,其中用到了无线模块由于英明神武的老板决定用ZigBee来做传输
结果就跑出了一些列的问题
其中一个就是MXC6202加速度传感器传输的数据用到了IIC协议
要用CC2430来做IIC的模拟
因为摸过了一段时间的CC2430,知道其中还是51的内核
以为是很简单的东西,应该和atmel的8051差不多的
但是做的时候又碰到了一系列的问题
最后绕了一圈才发现,哦,原来如此
2430芯片和51其中一个很大的区别就是:
必须人为的设置IO口的输入输出方向
也就是要设置每个端口的pin脚的PXDIR是1还是0
说还是太空泛了,那就上程序吧......
和51的程序相比,其实大部分还是相同的,我在这里就主要讲解一下两者不同的地方
只能算作一个平台的移植吧....
源程序会附在后面
SDA和SCL的读写
其实IIC总线协议的实现就是控制这两根线,让数据在规定的时候进行传输
其中就要最主要的就是对SCL的写操作和SDA的读写
以下是i2c_1.c的源程序,讲解就穿插其中.....
//i2c_1.c
#include "ioCC2430.h"
#include "i2c.h"
#define TRUE 1
#define FALSE 0
/*我的管脚定义是
SDA定义为P1.5
SCL定义为P1.4 */
#define SCL P1_4
#define SDA P1_5
/*
一个nop就是一条机器指令周期 = 1/32MHz
那32个nop就是1us啦
----这里是outman给我做出的讲解,在此再作感谢
*/
void Delay_1u(unsigned int microSecs) {
while(microSecs--)
{
/* 32 NOPs == 1 usecs */
asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
asm("nop"); asm("nop");
}
}
unsigned char error; /*错误提示,全局变量*/
/*
当通过CC2430的IO端口往外面写数据的时候
必须将对应的IO端口数据方向设置为输出
CC2430中DIRPX_Y为1时IO口为输出功能
DIRPX_Y为0时IO口为输入功能
我的SDA是P1.5,则SDA为输出功能时
P1口DIR应该是0010 0000
即0x20,其他可以依次类推......
啰嗦完毕,继续程序....
*/
void WriteSDA1(void)//SDA 输出1,相当于51里面的SDA=1 {
P1DIR |= 0x20;
SDA = 1;
}
void WriteSDA0(void)//SDA 输出0 {
P1DIR |= 0x20;
SDA = 0;
}
void WriteSCL1(void)//SCL 输出1 {
P1DIR |= 0x10;
SCL = 1;
}
void WriteSCL0(void)//SCL 输出1 {
P1DIR |= 0x10;
SCL = 0;
}
void ReadSDA(void)//这里设置SDA对应IO口DIR可以接收数据 {
P1DIR &= 0xDF;
}
/*启动I2C总线的函数,当SCL为高电平时使SDA产生一个负跳变*/
void I2C_Start_1(void)
{
WriteSDA1();
WriteSCL1();
Delay_1u(50);
WriteSDA0();
Delay_1u(50);
WriteSCL0();
Delay_1u(50);
}
/*终止I2C总线,当SCL为高电平时使SDA产生一个正跳变*/
void I2C_Stop_1(void)
{
WriteSDA0();
Delay_1u(50);
WriteSCL1();
Delay_1u(50);
WriteSDA1();
Delay_1u(50);
WriteSCL0();
Delay_1u(50);
}
/*发送0,在SCL为高电平时使SDA信号为低*/
void SEND_0_1(void) /* SEND ACK */
{
WriteSDA0();
WriteSCL1();
Delay_1u(50);
WriteSCL0();
Delay_1u(50);
}
/*发送1,在SCL为高电平时使SDA信号为高*/
void SEND_1_1(void)
{
WriteSDA1();
WriteSCL1();
Delay_1u(50);
WriteSCL0();
Delay_1u(50);
}
/*发送完一个字节后检验设备的应答信号*/
char Check_Acknowledge_1(void)
{
WriteSDA1();
WriteSCL1();
Delay_1u(50);
F0=SDA;
Delay_1u(50);
WriteSCL0();
Delay_1u(50);
if(F0==1)
return FALSE;
return TRUE;
}
void Write_Acknowledge_1(void)
{
WriteSDA0();
Delay_1u(50);
WriteSCL1();
Delay_1u(50);
WriteSCL0();
Delay_1u(50);
}
/*向I2C总线写一个字节*/
void WriteI2CByte_1(char b)
{
char i;
for(i=0;i<8;i++)
{
if((b<<i)&0x80)
{
SEND_1_1();
}
else
{
SEND_0_1();
}
}
}
/*从I2C总线读一个字节*/
char ReadI2CByte_1(void)
{
char b=0,i;
WriteSDA1();
for(i=0;i<8;i++)
{
WriteSCL0();
Delay_1u(50);
WriteSCL1();
Delay_1u(50);
ReadSDA();
F0=SDA;//寄存器中的一位,用于存储SDA中的一位数据
if(F0==1)
{
b=b<<1;
b=b|0x01;
}
else
b=b<<1;
}
WriteSCL0();
return b;
}
PS:
这里没有重要讲解IIC的实现原理
比如什么时候发送1,什么时候发送0
这里主要是讲解了一下在移植过程中需要注意的问题
如果有什么问题再问吧
整理一下需要注意的:
1.需要手动设置IO方向
2.延时设定的方式和晶振是有关系的,需要多长时间可以参照前面的程序
程序参考过robin's evolution的那篇用cc2430读取AT24CXX的驱动程序文章
以及感谢群里的on the way给我耐心讲解51的IIC
最后还是要感谢一下outman,谢谢你的提醒
over
- cc2530实现i2c数据线
- Ti CC2530 i2c 驱动
- cc2530
- CC2530
- CC2530
- ZIGBEE 低功耗的实现 (cc2530)
- 一个使用CC2530实现的Zigbee红绿灯
- CC2530 定时器3使用 -- 实现精确定时
- CC2530基于寄存器实现无线收发
- MCU实现I2C通信
- S3C2440 I2C实现
- Verilog的I2C实现
- I2C总线EEPROM实现
- 模拟i2c实现流程
- I2C FPGA实现
- 用C#实现电脑+数据线+手机模式发短信
- uiautomator如何实现脱机/脱离USB数据线运行脚本
- I2C 设备驱动程序 标准实现
- UILabel使用技巧(一)
- Sping bean的生命周期
- Java集合区别和联系
- windows的磁盘操作之六——获取系统所在物理磁盘号
- 单文档中多个子窗口
- cc2530实现i2c数据线
- java动态代理
- spring中Bean的生命周期总结
- 数组指针和指针数组的区别
- windows的磁盘操作之七——获取当前所有的物理磁盘号
- Josephu问题的解决
- Linux的Ubuntu与windows共享目录快捷方法
- windows的磁盘操作之八——格式化分区的思考
- 进程管理