I2C转UART
I2C转UART,51单片机普通IO口模拟I2C从机,解决UART不够的问题
/***************************************************************************
* 程序名:iic_uart.C
* 作者:
* 功能描述:实现IIC和UART数据交换
* 日期:2010.9.16 10.8最后修改
***************************************************************************/
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define LOC_address 0x48
sfr AUXR = 0x8e; //定时器倍率选择寄存器 10.17
sbit scl = P1^; //P1^3
sbit sda = P1^; //旧P1^4
sbit STROBE = P1^; //P1^6
sbit disp_led = P1^; //P3^7
void I2C_txbyte(uchar );
void uart_init(void );
void I2C_init(void );
void TIMER0_init(void );
void I2C_delay(void );
void I2C_respon(void );
uchar I2C_rxbyte(void );
void I2C_ack();
void start_scan();
void I2C_rxadd();
uchar I2C_rx7();
void uart_txbyte(uchar );
uchar xdata dat_I2C[] ,dat_UART[]; //10.16修改缓存大小
uchar num = ,
RX_flag = ,
NN, m = ,n = ,
TX_over = ;
uchar address = ,
rx_data,
START_flag = ,
STOP_flag = ,
PreState,
NowState,
DEV_address,
R_W,
uart_outtime=,
I2C_rx_outtime=,
TIME_MODE=;
/***************************************************************************
* 函数名:main()
* 功能描述:主程序
*
***************************************************************************/
void main()
{
uart_init(); //串口中断初始化
TIMER0_init(); //定时器0初始化
STROBE = ; //请求接受信号线初始化
disp_led = ; //指示灯初始化 1=熄灭 0=点亮
)
{
) //在接收数据吗?
{
) //等待数据超过0.5 秒了吗
{
TR0 = ; //关定时器0
uart_outtime = ; //UART等待计时清零
STROBE = ; //请求I2C上位机读数据
RX_flag = ; //清计时标志
TIME_MODE = ; //进入等待I2C读取计时模式 ,超过4S清空数据
TR0 = ; //开计时器0 ,10.17
}
}
start_scan(); //检测起始信号
)
{
START_flag = ; //开始信号清零
I2C_rxadd(); //收取地址及命令
if(DEV_address == LOC_address) //判断是否为本机地址
{
); //给予应答
m = ; //初始化m
) //主机向本机写数据
{
STROBE = (~STROBE); //通知主机收到起始信号 10.13
dat_I2C[m] = I2C_rxbyte(); //接收第一个字节
); //等待低电平结束
STROBE = (~STROBE); //10.7添加
);
m++;
);
PreState = sda; //记录SDA状态
)
{
) //在SCL为高端平期间检测结束信号
{
NowState = sda; //记录当前SDA状态
) //上升沿说明收到结束信号
{
STOP_flag = ; //收到结束信号
}
}
else
{
dat_I2C[m] = I2C_rx7(); //继续接收剩下的7位数据
);
);
m++;
);
}
}
STOP_flag = ;
;NN < m ;NN++)
{
uart_txbyte(dat_I2C[NN]); //将收到的数据通过UART发送给上位机
}
m=;
}
) //主机向本机读数据
{
TR0 = ; //关掉计时器 10 .17
STROBE = (~STROBE); //通知主机收到起始信号 10.13
);
I2C_txbyte(dat_UART[m]);
m++;
if(m == n) //如果数被读取完则通知上位机停止读
{
STROBE = ;
}
);
);
)
{
I2C_txbyte(dat_UART[m]); //将从UART接收到的数据通过I2C发送给主设备
m++;
if(m == n) //判断是否发送完了
{
STROBE = ;
}
); //等待低电平结束
);
}
);
STROBE = ;
m = ;
n = ;
disp_led = ; //读走后将灯熄灭
num = ; //清计时参数 10.17
TIME_MODE = ; //改回UART接收数据超时计时模式
}
}
}
}
}
/***************************************************************************
* 函数名:start_scan()
* 功能描述:起始信号检测子函数
*
***************************************************************************/
void start_scan()
{
NN = ;
PreState = sda; //记录当前SDA状态,用作比较
&& NN--)
{
NowState = sda;
&& NowState == ) //如果为上升沿则为开始信号
{
START_flag = ;
}
}
}
/***************************************************************************
* 函数名:uart_init
* 功能描述:串口中断初始化子函数
*
***************************************************************************/
void uart_init()
{
AUXR = 0x40; //T1为1T工作模式
TMOD = 0x21; //T1工作模式2
TH1 = 0xf7; //装填初值 .波特率为38400
TL1 = 0xf7; //f7
TR1 = ; //启动定时1
SM0 = ; //确定10位传输
SM1 = ;
REN = ; //打开允许接收
ES = ; //开总中断和串口中断
EA = ;
}
/***************************************************************************
* 函数名:TIMER0_init()
* 功能描述:定时器0初始化子函数
*
***************************************************************************/
void TIMER0_init()
{
TH0 = ( - ) / ; //装初值
TL0 = ( - ) % ;
ET0 = ; //开定时器中断允许
}
/***************************************************************************
* 函数名:uart_service()
* 功能描述:UART中断服务程序
*
***************************************************************************/
{
dat_UART[n] = SBUF; //存收到的数据
n++;
TR0 = ; //开定时器0 ,开始等待计时
RX_flag = ; //接收到数据标志,开始检测是否等待超时
uart_outtime = ; //等待超时计数清零
RI = ; //中断接收溢出标志位清零
}
/***************************************************************************
* 函数名:uart_txbyte()
* 功能描述:UART发送一个字节
*
***************************************************************************/
void uart_txbyte(uchar data1)
{
ES = ; //关串口中断
SBUF = data1; //发送数据
while( ! TI); //等待发送完毕
TI = ; //清溢出标志
ES = ;
}
/***************************************************************************
* 函数名:timer0{}
* 功能描述:定时器0中断服务程序,用来计算UART是否等待超时
*
***************************************************************************/
{
TH0 = ( - ) / ; //给定时器0装初值 50ms中断一次
TL0 = ( - ) % ;
num++;
) //用于UART接收数据超时计时
{
disp_led = ~disp_led; //显示灯闪
) //等待超过0.5秒到了
{
uart_outtime = uart_outtime + ; //等待超时计数加一
num = ;
}
}
) //用于I2C读走数据超时计时 10.17
{
disp_led = ; //灯常亮,等待读走
) //超过2秒未读走
{
num = ; //清计时参数
STROBE = ; //不通知I2C读取
n = ; //数据缓存下标清零 ,准备接收新数据
TIME_MODE = ; //改回UART接收数据超时计时模式
disp_led = ; //超时未读走则熄灭
TR0 = ; //关定时器0
}
}
}
/***************************************************************************
* 函数名:I2C_txbyte()
* 功能描述:I2C发送一个字节
*
***************************************************************************/
void I2C_txbyte(uchar dat_byte)
{
uchar i,temp;
temp = dat_byte;
);
); //等待主机释放数据总线
;i < ;i++) //从最高位开始,依次发送8位
{
temp = temp << ; //将要发送的数最高位移到CY中
sda = CY; //数据线发送CY中存的位数据
);
);
}
sda = ; //发完释放数据总线
}
/***************************************************************************
* 函数名:I2C_rxadd()
* 功能描述:接收设备地址
*
***************************************************************************/
void I2C_rxadd()
{
uchar i,j,k=;
);
;i < ;i++)
{
while( ! scl); //等待SCL由0变为1
)
j = ;
else
j = ;
k=(k << ) | j; //将收到的位放入K中
); //SCL高电平时等待
}
R_W=k&0x01; //主机是读还是写
DEV_address= (k >> ) & 0x7f; //求出前7位的设备地址
}
/***************************************************************************
* 函数名:I2C_rxbyte()
* 功能描述:I2C接收一个字节子函数
*
***************************************************************************/
uchar I2C_rxbyte()
{
uchar i,j,k=;
); //等待SCL拉低
;i < ;i++)
{
while( ! scl); //等待SCL由0变为1
)
j = ;
else
j = ;
k=(k << ) | j;
while(scl); //SCL高电平时等待
}
return(k); //将接收到的数据返回
}
/***************************************************************************
* 函数名:I2C_rx7()
* 功能描述:检测结束信号时收数据子函数
*
***************************************************************************/
uchar I2C_rx7()
{
uchar i,j,k=;
k=(k << ) | PreState; //将上一个位数据存入K中
;i < ;i++)
{
); //等待SCL变高
)
j = ;
else
j = ;
k=(k << ) | j; //将收到的位数据存入K
); //等待SCL拉低
}
return(k); //将收到的整个字节数据返回
}
测试代码如下:
/***************************************************************************
* 程序名:test.c
* 作者:
* 功能描述:测试I2C_uart 转接器
* 日期:2010.10.8
***************************************************************************/
#include<reg52.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
sbit sda = P2^; //定义数据线
sbit scl = P2^; //定义时钟线
sbit STROBE = P2^; //定义信号线
, //读数据缓存数组下标
tx = ,
rx_flag=;
uchar dat[]; //定义缓存数据数组
void delay(unsigned int i) //延时程序 ,延时约i ms
{
uint j,k;
;j--)
;k > ;k--);
}
void flash() //I2C所需时序延时 5us
{ ; ; }
/***************************************************************************
* 程序名:start()
* 功能: I2C起始信号
*
***************************************************************************/
void start() //启动I2C总线
{
sda = ;
flash();
scl = ;
flash();
sda = ;
flash();
scl = ;
flash();
}
/***************************************************************************
* 程序名: stop()
* 功能: I2C结束信号
*
***************************************************************************/
void stop() //停止I2C总线
{
sda = ;
flash();
scl = ;
flash();
sda = ;
flash();
}
/***************************************************************************
* 程序名: writex (uchar j )
* 功能: I2C写一个字节子函数
*
***************************************************************************/
void writex(unsigned char j)
{
unsigned char i,temp;
temp = j;
;i < ;i++)
{
temp = temp << ;
scl = ;
flash();
sda = CY; //将进位寄存器中的数赋给数据线
flash();
scl = ;
flash();
}
scl = ;
flash();
sda = ; //释放数据线
flash();
}
/***************************************************************************
* 程序名: readx()
* 功能: I2C读一个字节子函数
*
***************************************************************************/
unsigned char readx()
{
unsigned ;
scl = ;
flash();
sda = ; //释放数据线
;i < ;i++)
{
flash();
scl = ;
flash();
)
j = ;
else
j = ;
k=(k << ) | j;
scl = ;
}
flash();
return(k);
}
/***************************************************************************
* 程序名: clock()
* 功能: I2C等待应答子函数
*
***************************************************************************/
void clock()
{
unsigned ;
scl=;
flash();
) && (i < )) //SDA=0时说明有应答,无应答则等待直到超时
{
i++;
}
scl = ;
flash();
}
/***************************************************************************
* 程序名: IIC_read()
* 功能: I2C读数据
*
***************************************************************************/
void IIC_read() //通过I2C读数据
{
) //当STROBE=0则一直发送起始信号及首地址 ,直到转接器收到 ,将STROBE变为1
{
P1=; //灯亮,作测试用
start();
writex(0x91); //发器件地址和读指令
clock();
}
) //读取数据直到读完 ,转接器会将STROBE拉低以通知发送完毕
{
dat[m] = readx(); //将读到的数据存入缓存数组中
m++; //缓存数组下标向下移一位
clock();
}
stop(); //发送结束信号
}
/***************************************************************************
* 程序名: IIC_write(uchar info)
* 功能:通过I2C将一个字节数据发给转接器
*
***************************************************************************/
void IIC_write(uchar info)
{
) //在STROBE=1时写数据 ,即无读请求时
{
)
{
start();
writex(0x90); //10.13号修改,将首地址放到WHILE外
clock();
}
writex(info); //写数据
clock();
stop();
}
else //在STROBE=0时写数据 ,此时有读请求
{
)
{
start();
writex(0x90);
clock();
}
writex(info); //写数据
clock();
stop();
}
}
/***************************************************************************
* 程序名: main()
* 功能: 程序主函数
*
***************************************************************************/
void main()
{
scl = ;
delay(); //初始化I2C
sda = ;
delay();
)
{
) //读请求
{
// IIC_write('g');
// IIC_write('e');
// IIC_write('t'); //测试用
// IIC_write(':');
IIC_read(); //读数据
delay(); //稍作延时,约1毫秒 ,紧随读数据之后
rx_flag = ; //读取到数据标志置1
P1=dat[]; //10.8,作测试用
}
) //读到数据了吗?
{
rx_flag = ;
;tx < m ;tx++) //将收到的数据返回
{
IIC_write(dat[tx]);
}
m = ; //将数据缓存下标清零
}
}
}
I2C转UART的更多相关文章
- SPI、I2C、UART(转)
UART与USART(转) UART需要固定的波特率,就是说两位数据的间隔要相等. UART总线是异步串口,一般由波特率产生器(产生的波特率等于传输波特率的16倍).UART接收器.UART发送器组成 ...
- SPI、I2C、UART、I2S、GPIO、SDIO、CAN 简介
转自http://sanwen.net/a/fmxnjoo.html SPI.I2C.UART.I2S.GPIO.SDIO.CAN,看这篇就够了 总线 总线,总要陷进里面.这世界上的信号都一样,但是总 ...
- SPI、I2C、UART三种串行总线协议的区别和SPI接口介绍(转)
SPI.I2C.UART三种串行总线协议的区别 第一个区别当然是名字: SPI(Serial Peripheral Interface:串行外设接口); I2C(INTER IC BUS) UART( ...
- SPI、I2C、UART、I2S、GPIO、SDIO、CAN
总线,总线,总要陷进里面.这世界上的信号都一样,但是总线却成千上万,让人头疼. 总的来说,总线有三种:内部总线.系统总线和外部总线.内部总线是微机内部各外围芯片与处理器之间的总线,用于芯片一级的互连: ...
- 串行总线 —— I2C、UART、SPI
I2C,也叫 IIC,是一种常见的串行总线,它只需要两根线即可在连接于总线上的器件之间传送信息. 0. 电气知识 开漏输出:Open drain output,不输出电压,低电平时接地,高电平时不接地 ...
- I2S/PCM/IOM-2、I2C/SPI/UART/GPIO/slimbus
概述 I2S,PCM,IOM-2都是数字音频接口,传数据的. I2C,SPI,UART,GPIO是控制接口,传控制信令的. I2S I2S(Inter-IC Sound Bus)是飞利浦公司为数字音频 ...
- SPI、I2C、UART三种串行总线协议的区别
第一个区别当然是名字: SPI(Serial Peripheral Interface:串行外设接口); I2C(INTER IC BUS) UART(Universal Asynchronous R ...
- UART,USART,SPI,I2C等总线的介绍与区别20160526
首先来说一下UART和USART的区别: 1.字面意义: UART:universal asynchronous receiver and transmitter通用异步收发器: USART:univ ...
- SPI,UART,I2C都有什么区别,及其各自的特点
区别: SPI:高速同步串行口.3-4线接口,收发独立.可同步进行 UART:通用异步串行口.按照标准波特率完成双向通讯,速度慢 I2C:一种串行传输方式,三线制,网上可找到其通信协议和用法的 3根线 ...
随机推荐
- clock_gettime测代码运行时间
//函数原型: // long clock_gettime (clockid_t which_clock, struct timespec *tp); //参数列表: // CLOCK_REALTIM ...
- Android自己定义控件而且使其能够在xml中自己定义属性
为什么要自己定义View android开发中自己定义View的优点是显而易见的.比方说以下的这个顶部导航,它被设计出如今应用的每一个界面,但每次的内容却不尽同样.我们不能在每一个layout资源中都 ...
- android 06 LinearLayout
xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:la ...
- 走进 Facebook POP 的世界
POP: 一个流行的可扩展的动画引擎iOS,它支持spring和衰变动态动画,使其可用于构建现实,基于物理交互.Objective - C API允许快速集成, 对于所有的动画和过渡他是成熟的. 解释 ...
- ckeditor 敏感词标记显示处理方法
直接在原型添加方法: (function () { /* * 取消所有高亮 */ CKEDITOR.editor.prototype.CancleSensitiveWordsHighlight = f ...
- 他们都没告诉你适配 Android N 需要注意什么
还记得 6.0 对 Apache Http 库的废除导致的应用崩溃吗?还记得 6.0 中 MAC id 始终返回为空导致的唯一 id 混合生成算法大幅失效吗? 1. Android 中 Java 的实 ...
- Driving the Activity Lifecycle
Before Robolectric 2.2, most tests created Activities by calling constructors directly, (new MyActiv ...
- hadoop集群环境搭建之zookeeper集群的安装部署
关于hadoop集群搭建有一些准备工作要做,具体请参照hadoop集群环境搭建准备工作 (我成功的按照这个步骤部署成功了,经实际验证,该方法可行) 一.安装zookeeper 1 将zookeeper ...
- 自己写的自动生成动态边框的jquery小插件
思路就是在元素四周添加<ul>列表,然后周期性地改变它的颜色,实现动态的效果,不支持ie7.ie8 预览链接http://gorey.sinaapp.com/myBorder/border ...
- 关于c++中的引用
引用是个别名. 1.引用是否占用空间 引用是否占用空间,此处是指广义上的占用内存空间,即为该对象新开辟一块内存.这个需要分不同的情况. 首先看一下常引用(const 引用). 这里关于常引用在c++ ...