硬件I2C(查询方式)以STC8F2K08S2单片机为例

  • 一、I2C相关的寄存器
    • ① I2C 配置寄存器
    • ② I2C 主机控制寄存器
    • ③ I2C 主机辅助控制寄存器
    • ④ I2C 主机状态寄存器
    • ⑤ I2C 数据寄存器
    • ⑥ 外设端口切换控制寄存器 1
    • ⑦ 外设端口切换控制寄存器 2
  • 二、程序编写
    • ① 寄存器和相关宏定义
    • ② 硬件I2C初始化
    • ③ 硬件I2C操作代码
    • ④ BMP085 读写例程
    • ⑤ 串口代码

一、I2C相关的寄存器

① I2C 配置寄存器

② I2C 主机控制寄存器



③ I2C 主机辅助控制寄存器

④ I2C 主机状态寄存器


⑤ I2C 数据寄存器

⑥ 外设端口切换控制寄存器 1

⑦ 外设端口切换控制寄存器 2

二、程序编写

① 寄存器和相关宏定义

sfr P_SW2 = 0xBA;       //外设端口切换寄存器 2#define I2CCFG     (*(unsigned char volatile xdata *)0xfe80)
#define I2CMSCR     (*(unsigned char volatile xdata *)0xfe81)
#define I2CMSST     (*(unsigned char volatile xdata *)0xfe82)
#define I2CTXD      (*(unsigned char volatile xdata *)0xfe86)
#define I2CRXD      (*(unsigned char volatile xdata *)0xfe87)#define I2C_S0 0x10
#define I2C_S1  0x20
#define EAXFR   0x80        //I2C功能寄存器为扩展 SFR,逻辑地址位于 XDATA 区域,访问前需要将 P_SW2(BAH)寄存器的最高位(EAXFR)置 1sbit SDA = P3^3;
sbit SCL = P3^2;#ifndef uchar#define uchar unsigned char
#endif
#ifndef uint#define uint  unsigned int
#endif

② 硬件I2C初始化

void init_i2c(void)
{uchar temp = 0x00;                            //                                      //切换到第一组I2C
//  temp &= ~(I2C_S0 | I2C_S1);            //I2C_S0=0 I2C_S1=0
//                                      //(P1.5/SCL, P1.4/SDA)//                                        //切换到第二组I2C
//  temp &= ~(I2C_S0 | I2C_S1);            //I2C_S0=1 I2C_S1=0
//  temp |= I2C_S0;                        //(P2.5/SCL, P2.4/SDA)//                                        //切换到第三组I2C
//  temp &= ~(I2C_S0 | I2C_S1);            //I2C_S0=0 I2C_S1=1
//  temp |= I2C_S1;                        //(P7.7/SCL, P7.6/SDA)//切换到第四组I2Ctemp |= (I2C_S0 | I2C_S1);            //I2C_S0=1 I2C_S1=1//(P3.2/SCL, P3.3/SDA)temp |= EAXFR;                      //I2C功能寄存器为扩展 SFR,逻辑地址位于 XDATA 区域,访问前需要将 P_SW2(BAH)寄存器的最高位(EAXFR)置 1P_SW2 = temp;I2CCFG = 0xE0;                              //使能I2C主机模式I2CMSST = 0x00;
}

③ 硬件I2C操作代码

void wait()
{while(!(I2CMSST & 0x40));I2CMSST &= ~0x40;
}void start()
{I2CMSCR = 0x01;                             //发送START命令wait();
}void send_data(uchar dat)
{I2CTXD = dat;                               //写数据到数据缓冲区I2CMSCR = 0x02;                             //发送SEND命令wait();
}void recv_ack()
{I2CMSCR = 0x03;                             //发送读ACK命令wait();
}uchar recv_data()
{I2CMSCR = 0x04;                             //发送RECV命令wait();return I2CRXD;
}void send_ack()
{I2CMSST = 0x00;                             //设置ACK信号I2CMSCR = 0x05;                             //发送ACK命令wait();
}void send_nack()
{I2CMSST = 0x01;                             //设置NAK信号I2CMSCR = 0x05;                             //发送ACK命令wait();
}void stop()
{I2CMSCR = 0x06;                             //发送STOP命令wait();
}

④ BMP085 读写例程

#define  BMP085_SlaveAddress     0xEE        //定义器件在IIC总线中的从地址#define OSS                 0
#define p0                  101325.0uchar send[6];xdata short ac1;
xdata short ac2;
xdata short ac3;
xdata unsigned short ac4;
xdata unsigned short ac5;
xdata unsigned short ac6;
xdata short b1;
xdata short b2;
xdata short mb;
xdata short mc;
xdata short md;//10进制数字转ASCII字符
void Conversion(long temp_data, uchar *pAscii)
{  *(pAscii + 5) = temp_data / 100000 + 0x30;        //十万temp_data = temp_data % 100000;                    //取余运算 *(pAscii + 4) = temp_data / 10000 + 0x30;     //万temp_data = temp_data % 10000;                  //取余运算*(pAscii + 3) = temp_data / 1000 + 0x30;       //千temp_data = temp_data % 1000;                   //取余运算*(pAscii + 2) = temp_data / 100 + 0x30;            //百temp_data = temp_data % 100;                    //取余运算*(pAscii + 1) = temp_data / 10 + 0x30;         //十temp_data = temp_data % 10;                     //取余运算*(pAscii + 0) = temp_data + 0x30;              //个
}//单字节写入
void Single_Write(uchar SlaveAddress, uchar REG_Address, uchar REG_data)
{start();                   //起始信号send_data(SlaveAddress);  //发送设备地址+写信号recv_ack();send_data(REG_Address);     //写寄存器地址recv_ack(); send_data(REG_data);        //写寄存器数据recv_ack();stop();                      //发送停止信号
}//单字节读取
uchar Single_Read(uchar SlaveAddress, uchar REG_Address)
{  uchar REG_data;start();                          //起始信号send_data(SlaveAddress);           //发送设备地址+写信号recv_ack();send_data(REG_Address);            //写寄存器地址recv_ack();start();                          //起始信号send_data(SlaveAddress + 1);         //发送设备地址+读信号recv_ack();REG_data = recv_data();              //读出寄存器数据send_nack();   stop();                           //停止信号return REG_data;
}//读出BMP085内部数据,连续两个
short Multiple_read(uchar SlaveAddress, uchar ST_Address)
{   uchar msb, lsb;short _data;start();                          //起始信号send_data(SlaveAddress);    //发送设备地址+写信号recv_ack();send_data(ST_Address);             //写寄存器地址recv_ack();start();                          //起始信号send_data(SlaveAddress + 1);         //发送设备地址+读信号recv_ack();msb = recv_data();                 //BUF[0]存储send_ack();                       //回应ACKlsb = recv_data();     send_nack();                      //最后一个数据需要回NACKstop();                           //停止信号Delay5ms();_data = msb << 8;_data |= lsb;    return _data;
}//BMP085读温度
long BMP085_Read_Temp(void)
{Single_Write(BMP085_SlaveAddress, 0xF4, 0x2E);Delay5ms();  //最大时间4.5msreturn (long)Multiple_read(BMP085_SlaveAddress, 0xF6);
}
//BMP085读压力
long BMP085_Read_Pressure(void)
{long pressure = 0;Single_Write(BMP085_SlaveAddress, 0xF4, 0x34);Delay5ms();                         //最大时间4.5mspressure = Multiple_read(BMP085_SlaveAddress, 0xF6);pressure &= 0x0000FFFF;return pressure;
}//初始化BMP085,根据需要请参考pdf进行修改
void Init_BMP085()
{ac1 = Multiple_read(BMP085_SlaveAddress, 0xAA);ac2 = Multiple_read(BMP085_SlaveAddress, 0xAC);ac3 = Multiple_read(BMP085_SlaveAddress, 0xAE);ac4 = Multiple_read(BMP085_SlaveAddress, 0xB0);ac5 = Multiple_read(BMP085_SlaveAddress, 0xB2);ac6 = Multiple_read(BMP085_SlaveAddress, 0xB4);b1 =  Multiple_read(BMP085_SlaveAddress, 0xB6);b2 =  Multiple_read(BMP085_SlaveAddress, 0xB8);mb =  Multiple_read(BMP085_SlaveAddress, 0xBA);mc =  Multiple_read(BMP085_SlaveAddress, 0xBC);md =  Multiple_read(BMP085_SlaveAddress, 0xBE);
}
//开启转换
void BMP085_Convert()
{long ut;long up;long x1, x2, b5, b6, x3, b3, p;unsigned long b4, b7;long temperature;long pressure;double altitude;ut = BMP085_Read_Temp();//ut = BMP085_Read_Temp();       // 读取温度up = BMP085_Read_Pressure();//up = BMP085_Read_Pressure();  // 读取压强x1 = ((long)ut - ac6) * ac5 >> 15;x2 = ((long) mc << 11) / (x1 + md);b5 = x1 + x2;temperature = (b5 + 8) >> 4;Conversion(temperature, send);uart_sendstring("Temperature: ");       //温度显示uart_sendchar(send[2]); uart_sendchar(send[1]); uart_sendchar('.'); uart_sendchar(send[0]);uart_sendstring("℃\r\n");//温度单位memset(send, 0x00, 6);b6 = b5 - 4000;x1 = (b2 * (b6 * b6 >> 12)) >> 11;x2 = ac2 * b6 >> 11;x3 = x1 + x2;b3 = (((long)ac1 * 4 + x3) + 2)/4;x1 = ac3 * b6 >> 13;x2 = (b1 * (b6 * b6 >> 12)) >> 16;x3 = ((x1 + x2) + 2) >> 2;b4 = (ac4 * (unsigned long) (x3 + 32768)) >> 15;b7 = ((unsigned long) up - b3) * (50000 >> OSS);if( b7 < 0x80000000)p = (b7 * 2) / b4 ;else  p = (b7 / b4) * 2;x1 = (p >> 8) * (p >> 8);x1 = (x1 * 3038) >> 16;x2 = (-7357 * p) >> 16;pressure = p + ((x1 + x2 + 3791) >> 4);Conversion(pressure, send);uart_sendstring("Pressure: ");       //显示压强uart_sendchar(send[5]); uart_sendchar(send[4]); uart_sendchar(send[3]); uart_sendchar('.'); uart_sendchar(send[2]);uart_sendchar(send[1]); uart_sendchar(send[0]); uart_sendstring("kPa\r\n");//压强单位memset(send, 0x00, 6);altitude = 44330.0 * (1 - pow((float)pressure / p0, 1.0 / 5.255)) * 100;//精度cmConversion(altitude, send);uart_sendstring("Altitude:");    //显示海拔uart_sendchar(send[4]); uart_sendchar(send[3]);uart_sendchar(send[2]);uart_sendchar('.'); uart_sendchar(send[1]); uart_sendchar(send[0]); uart_sendstring("m\r\n");//海拔单位memset(send, 0x00, 6);
}
//主函数
void main(void)
{init_uart();init_i2c();ES = 1;        //使能串口中断EA = 1;        //使能总中断Init_BMP085();while(1){BMP085_Convert();uart_sendstring("\r\n");uart_sendstring("\r\n");uart_sendstring("\r\n");Delay500ms();Delay500ms();Delay500ms();Delay500ms();}
}

⑤ 串口代码

#ifndef FOSC#define FOSC 24000000L       //系统频率24MHz
#endif
#define BAUD 115200           //UART波特率sfr P_SW1 = 0xa2;
sfr AUXR  = 0x8e;
sfr T2H   = 0xd6;
sfr T2L   = 0xd7;bit busy;//初始化串口
void init_uart()
{P_SW1 = 0x00;                               //RXD/P3.0, TXD/P3.1
//  P_SW1 = 0x40;                               //RXD_2/P3.6, TXD_2/P3.7
//  P_SW1 = 0x80;                               //RXD_3/P1.6, TXD_3/P1.7
//  P_SW1 = 0xc0;                               //RXD_4/P4.3, TXD_4/P4.4SCON = 0x50;T2L  = (65536 - FOSC / BAUD / 4) % 256;     //65536 - FOSC / BAUD / 4T2H  = (65536 - FOSC / BAUD / 4) / 256;AUXR = 0x15;                                //启动定时器
}//串口发送单个字符
void uart_sendchar(uchar dat)
{while (busy);busy = 1;SBUF = dat;
}//串口发送字符串
void uart_sendstring(uchar *p)
{while(*p){uart_sendchar(*p++);}
}//串口接收中断
void uart_isr() interrupt 4 using 1
{if(TI){TI = 0;busy = 0;}if(RI){RI = 0;}
}

STC8系列单片机硬件I2C使用教程(一)相关推荐

  1. STC8系列单片机硬件I2C使用教程(二)

    硬件I2C(中断方式)以STC8F2K08S2单片机为例 一.I2C相关的寄存器 二.I2C中断相关的寄存器 ① I2C中断源 ② I2C中断允许位 ③ I2C中断标志位 三.程序编写 ① 寄存器和相 ...

  2. #STC8A8K# #STC8F1K# #STC8G1K# #STC8H1K# ——STC8系列单片机整体评价

    成就更好的自己 声明:这不是广告,只是发表看法和吐槽,不吹不擂: 本文以STC8A8K64S4A12为例,简要分析一下STC8系列: STC(宏晶科技)公司作为国内的一家MCU生产公司,专注于8051 ...

  3. STM32F 单片机硬件I2C Busy标志导致的I2C卡死的处理办法

    STM32F 单片机硬件I2C Busy标志导致的I2C卡死的处理办法 在调试多用户表的时候,发现如果人为短接I2C的SDA或SLK脚后,I2C的SR2的Busy标志将会置1,并且试了很多种办法也无法 ...

  4. STM32单片机硬件I2C读取AHT10温湿度传感器数据

    STM32使用硬件IIC读取AHT10温湿度传感器的数据并显示在0.96寸OLED屏上. 我用的单片机是STM32F103C8T6,程序用的是ST标准库写的. STM32使用硬件I2C读取SHTC3温 ...

  5. STM32单片机硬件I2C驱动程序(查询方式)

    本文章原始地址:http://feotech.com/?p=69 本程序主要用于驱动STM32单片机芯片的硬件I2C寄存器,实现通过使用芯片自带的I2C寄存器进行数据的发送与接收. 本例程中采用I2C ...

  6. STM32单片机硬件I2C驱动程序(软件轮询方式)---摘自:FeoTech

    感谢原作者:FeoTech   原文网址:http://feotech.com/?p=69 本程序主要用于驱动STM32单片机芯片的硬件I2C寄存器,实现通过使用芯片自带的I2C寄存器进行数据的发送与 ...

  7. ​HC32L130/HC32L136华大单片机硬件I2C驱动代码(从机为存储芯片EEPROM(AT24C02,FM24CL64B))​

    由于同事嫌弃模拟I2C速度太慢了 所以想改成硬件I2C 我试过例程的驱动代码 不太行 存储地址也是8位的 所以参考了一些博文 修改了下例程的代码 亲测有效 希望能帮到大家 代码如下 这里用的是I2C0 ...

  8. 瑞萨单片机-硬件I2C从设备

    开发环境 1.e2 studio 2.R5F1115AxFL 概述 1.网上关于I2C从机的资料很少,在这里分享下我在瑞萨单片机上实现I2C从机,根据主机发来的数据,从机返回或者保存数据 2.R5F1 ...

  9. 【VSCode PlatformIO】STC8系列SDCC专用头文件内容分享

    [VSCode PlatformIO]STC8单片机开发专用头文件内容分享 相关篇<[VSCode PlatformIO]STC15单片机开发专用头文件内容分享> 如果使用VSCode P ...

最新文章

  1. 好像最近买了很多东西
  2. Linux Java Web 服务器搭建之tomcat安装
  3. python快速入门第3版 数据_Python 快速入门 第3版
  4. 可以弹的钢琴,很不错(转)
  5. 向量距离计算 java_Milvus 向量搜索引擎开源了!
  6. 微信小程序调试之【不在以下合法域名列表中】
  7. Android中CursorLoader的使用、原理及注意事项
  8. 传高盛与德劭前合伙人组5亿美元私募基金
  9. [CentOS7]安装tomcat并开启自启动
  10. 第二阶段冲刺报告(三)
  11. 安装matlab 2016a win10 64bit系统
  12. 算法笔记(胡凡)刷题笔记目录
  13. 基于Multisim的循环彩灯控制器仿真设计
  14. 如何设置论文目录左对齐?
  15. golang:context介绍
  16. 附彩蛋|Spring Security 竟然故意延长登录时间?知道真相的我惊呆了!
  17. 自动扫福脚本(Android版)
  18. 高并发存储优化篇:诸多策略,缓存为王
  19. 湖南大学计算机专业女生宿舍,湖南大学宿舍条件,宿舍环境图片(10篇)
  20. What's New in Dundas Chart 6.1

热门文章

  1. Sysbench常用命令
  2. 洛谷——P2559 [AHOI2002]哈利·波特与魔法石
  3. 温湿度NB-IOT上云问题
  4. 第三课向量与平面直线方程
  5. EasyTouch学习
  6. 视觉SLAM--ORB特征简介
  7. 【转】QMouseEvent鼠标事件简介
  8. 阻止冒泡和阻止默认事件——cancelBubble和stopPropagation
  9. 曹颖生日会带货直播近5600万,一周年交出漂亮成绩单
  10. Solidworks如何保存为网页可以浏览的3D格式