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根线 ...
随机推荐
- spring beans源码解读之--BeanFactory进化史
BeanFactory是访问bean容器的根接口,它是一个bean容器的基本客户端视图. 先让我们看看beanfactory的前生后世吧! beanFactory有四个重要的子接口: SimpleJn ...
- CTE在Oracle和Sqlserver中使用的差异
CTE是一个很好用的工具,他可以帮助我们清晰代码结构,减少临时表使用,同时oracle和sqlserver都提供支持.但在oracle和sqlserver中使用CTE也存在一定区别. Oracle使用 ...
- 第四篇:python 高级之面向对象初级
python 高级之面向对象初级 python 高级之面向对象初级 本节内容 类的创建 类的构造方法 面向对象之封装 面向对象之继承 面向对象之多态 面向对象之成员 property 1.类的创建 ...
- 快速记忆JavaScript中exec和match的使用
JS模式匹配中exec,match用得非常多,所以掌握其用法对我们进行字符串的处理帮助非常大 1.exec的定义其用法 exec与match主要的不同是,exec是正则表达式里面的方法. ...
- js多行字符串
最基本的做法是: js 代码 var str = "111\n222\n333"; 但是这样不好排版.JavaScript 本身支持“\”的断句方式,于是可以这样写: js 代码 ...
- hibernate通过判断参数动态组合Hql语句,生成基本通用查询
// public List find(Station entity) { List reuslt = null; // 字符串辅助类 StringBuffer hql = new StringBuf ...
- Android开发手记(29) 基于Http的LaTeX数学公式转换器
本文将讲解如何通过codecogs.com和Google.com提供的API接口来将LaTeX数学函数表达式转化为图片形式.具体思路如下: (1)通过EditText获取用户输入的LaTeX数学表达式 ...
- ReactiveCocoa入门教程——第一部分
ReactiveCocoa iOS 翻译 2015-01-22 02:33:37 11471 6 15 本文翻译自RayWenderlich ReactiveCocoa ...
- 通常我们使用[NSDate date]方法得到的时间与当前时间不一致,如何解决?
NSDate *date = [NSDate date]; NSTimeZone *zone = [NSTimeZone systemTimeZone]; NSInteger interv ...
- Python:if-while-for
#!/usr/bin/python3 #if elif else print("开始猜数字游戏") num = int(input("请输入数字")) stan ...