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根线 ...
随机推荐
- [PWA] Keynote: Progressive Web Apps across all frameworks
PWA: Add to home screen Angular Universal Server side rendering: for achieving better proference on ...
- 他们都没告诉你适配 Android N 需要注意什么
还记得 6.0 对 Apache Http 库的废除导致的应用崩溃吗?还记得 6.0 中 MAC id 始终返回为空导致的唯一 id 混合生成算法大幅失效吗? 1. Android 中 Java 的实 ...
- css(字体,文本,边距,边框,阴影,背景,渐变,多重背景,列表)
font-family 设置字体名称 可以使用多个名称,用逗号分隔,浏览器则按照先后顺序依次使用可用字体 p { font-family:'宋体','黑体','Arial'; } font-size ...
- cookie防篡改
概述: 除了 session 外,一般不会在客户端的 cookies 里保存过于重要的凭据,但电商应用有时候不可避免地存储了一些敏感数据到客户端,当然不希望被篡改. 目的: 让服务器端能识别cooki ...
- OC - 27.CATransition
概述 简介 CATransition又称转场动画,是CAAnimation的子类,可以直接使用 转场动画主要用于为图层提供移入/移出屏幕的动画效果 转场动画常见的应用是UINavigationCont ...
- JDK常用类_util
集合 Collection:集合顶层接口 AbstractCollection:集合抽象类 关联数组 Map:顶层接口 AbstractMap:抽象类实现,提供了子类的通用操作 HashMap:哈希表 ...
- 明解C语言,练习13-3,从文件中读入个人信息,按身高排序后显示
#include <stdio.h> #define NUMBER 6 #define F_PATH "D:\\C_C++\\ec13-3\\hw.dat" typed ...
- Python下调用json.dumps中文显示问题解决办法
json.dumps在默认情况下,对于非ascii字符生成的是相对应的字符编码,而非原始字符,例如: import json js = json.loads('{"haha": & ...
- Mobile开发之meta篇
Mobile开发之meta篇 <meta name="viewport" content="width=device-width, initial-scale=1, ...
- contos 安装jdk1.8
JDK安装配置 查看centos系统32位还是64位, 使用命令uname -a;x86是386,586系列的统称,主要是指指令集合.X64才是cpu对64位计算的支持版本. 1. 下载jdk,本例使 ...