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根线 ...
随机推荐
- c++ 字符串流 sstream(常用于格式转换) 分类: C/C++ 2014-11-08 17:20 150人阅读 评论(0) 收藏
使用stringstream对象简化类型转换 C++标准库中的<sstream>提供了比ANSI C的<stdio.h>更高级的一些功能,即单纯性.类型安全和可扩展性.在本文中 ...
- golang 学习笔记
golan 声明的变量必须要用到? 语法 a,b:=2323; b为 bool 类型 结构体的赋值 需要用到逗号分隔字段 并且最后一个字段后也必须加上逗号 这和 JavaScript 的对象不一样哦 ...
- [io PWA] Great libraries and tools for great Progressive Web Apps
sw-toolbox: Github It provides a cononical implementation of all the runtime caching strategies that ...
- MyEclipse_6.0.1GA_E3.3.1集成版下载地址
因在开发中经常使用到myeclipse 对比相关版本,还是觉得6.0 –6.5 比较适合开发,其他的开发起来比较卡,下面是下载地址 MyEclipse_6.0.1GA_E3.3.1集成版下载地址: ...
- FastDFS安装配置手册
文件服务器分布式系统安装手册 本文档详细的介绍了FastDFS的最小集群安装过程.集群环境如下: tracker:20.2.64.133 .用于调度工作,在访问上起负载均衡的作用. group1: s ...
- Python之路【第五篇】:面向对象和相关
Python之路[第五篇]:面向对象及相关 面向对象基础 基础内容介绍详见一下两篇博文: 面向对象初级篇 面向对象进阶篇 其他相关 一.isinstance(obj, cls) 检查是否obj是否 ...
- Spire.Barcode好用的条码生在组件
由于项目的需要,今天在网上找了一下条码的组件,发现了一个简单易用的组件,使用简单,几句代码就搞定了.
- 试着开发chrome插件
我的第一个chrome插件,是app形式的 代码如下 创建一个文件: 1.manifest.json { "version": "1.0", "man ...
- 枚举,Enum,常规使用demo记录
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mv ...
- 关于SQL IO的一些资料
前些天在做优化的时候发现一个有意思的现象,单纯的SQL执行很快,秒级返回,但是页面响应却很慢,一直在想这是为什么呢?有点怀疑服务器的IO有问题,想了想做了个实验,模拟了同样的场景,通过优化SQL将 ...