以下为.h文件:

定义了PA1为SDA,PA2为SCL


#ifndef __I2C_H
#define __I2C_H
#include "stm8s.h"
#include "stm8s_gpio.h"
#include "tim1.h"
#include "uart.h"
#include <iostm8s103f3.h>
#include <intrinsics.h>#define SCL              PA_ODR_ODR2
#define SDA              PA_ODR_ODR1
#define SDAM             PA_IDR_IDR1
#define SET_SCL_OUT()    {PA_DDR_DDR2=1; PA_CR1_C12 = 1; PA_CR2_C22 = 0;}
#define SET_SDA_OUT()    {PA_DDR_DDR1=1; PA_CR1_C11 = 1; PA_CR2_C21 = 0;}
#define SET_SDA_IN()     {PA_DDR_DDR1=0; PA_CR1_C11 = 0; PA_CR2_C21 = 0;}void IIC_Init(void);
void Delay_us(u8 z);
void I2C_Start(void);
void I2C_Stop(void);
void IIC_Ack(void);
void IIC_NAck(void);
uint8_t IIC_Wait_Ack(void);
void IIC_Send_Byte(uint8_t txd);
uint8_t IIC_Read_Byte(uint8_t ack);
void  Device_WriteData(uint8_t DeciveAddr,uint8_t DataAddr,uint8_t Data);
void Decive_ReadData(uint8_t DeciveAddr,uint8_t DataAddr,uint8_t *ReciveData,uint8_t num);#endif

以下为.c文件:

#include "I2C.h"
//--------------------------------------------------------------
// Prototype      : void I2C_Start(void)
// Calls          : Delay_5us()
// Description    : Start Singnal
//--------------------------------------------------------------
void IIC_Init(void)
{SET_SCL_OUT();SET_SDA_OUT(); SCL = 1;SDA = 1;
}
//--------------------------------------------------------------
// Prototype      : void Delay_5us(void)
// Description    : 大约延时5us
//--------------------------------------------------------------
void Delay_us(u8 z)
{//u8 i;                   //fcpu 8MHz 时//for (i=50; i>0; i--);while(z--){nop();nop();nop();nop();}
}
//--------------------------------------------------------------
// Prototype      : void I2C_Start(void)
// Calls          : Delay_5us()
// Description    : Start Singnal
//--------------------------------------------------------------
void I2C_Start(void)
{// SDA 1->0 while SCL High//SCL高电平期间,SDA出现一个下降沿表示起始信号SET_SDA_OUT();SDA = 1;     //数据线先保持为高,起始信号要该口的下降沿 Delay_us(4);SCL = 1;        //时钟线保持为高            Delay_us(40);    //有一个大概5us的延时具体以器件而定            SDA = 0;        //数据线拉低出现下降沿           Delay_us(4);    //延时 一小会,保证可靠的下降沿            SCL = 0;        //拉低时钟线,保证接下来数据线允许改变
}//--------------------------------------------------------------
// Prototype      : void I2C_Stop(void)
// Calls          : Delay_5us()
// Description    : Stop Singnal
//--------------------------------------------------------------
void I2C_Stop(void)
{// SDA 0->1 while SCL High//SCL高电平期间,SDA产生一个上升沿 表示停止SET_SDA_OUT();SCL = 0;Delay_us(2);SDA = 0;     //保证数据线为低电平Delay_us(40);SCL = 1;       //先保证时钟线为高电平Delay_us(10);    //延时 以得到一个可靠的电平信号            SDA = 1;        //数据线出现上升沿           Delay_us(40);    //延时 保证一个可靠的高电平
}//应答函数
void IIC_Ack(void)
{//数据线一直保持为低电平,时钟线出现上升沿即为应答SET_SDA_OUT();Delay_us(10);SDA = 0;Delay_us(10);SCL = 0;Delay_us(40);SCL = 1;Delay_us(40);//应答完成后 将时钟线拉低 允许数据修改SCL = 0;
}
//非应答
void IIC_NAck(void)
{//非应答即相反 与应答区别即为数据线保持高电平即可SET_SDA_OUT();Delay_us(10);SDA = 1;Delay_us(10);SCL = 0;Delay_us(40);SCL = 1;Delay_us(40);//最后要将时钟线拉低 允许数据变化SCL = 0;
}
//等待应答
uint8_t IIC_Wait_Ack(void)//0为有应答,1为无应答
{//应答等待计数uint8_t ackTime = 0;//先将数据线要设置成输入模式本程序未体现,有应答则会出现下降沿SCL = 0;SET_SDA_OUT();Delay_us(10);   SDA = 1;//Delay_us(30);SET_SDA_IN();//切换为输入模式//时钟线拉高SCL = 1;Delay_us(30);//等待数据线拉低应答while(SDAM){//如果在该时间内仍未拉低ackTime ++;if(ackTime > 250){//认为非应答 停止信号I2C_Stop();return 1;}}SCL = 0;return 0 ;
}void IIC_Send_Byte(uint8_t txd)
{//定义一个计数变量uint8_t i;SET_SDA_OUT();//将时钟线拉低允许数据改变
//    SCL = 0;//按位发送数据for(i = 0;i < 8; i ++){Delay_us(2);if((txd&0x80)>>7) //0x80  1000 0000SDA=1;elseSDA=0;txd<<=1;    Delay_us(20);   SCL=1;Delay_us(20);  SCL=0; Delay_us(20); }
}//返回值为收到的数据
//参数为是否应答1应答0不应答
uint8_t IIC_Read_Byte(uint8_t ack)
{//定义计数变量uint8_t i = 0;//定义接收变量uint8_t receive = 0;//此时要把数据线的模式切换为输入模式 本程序中不予体现SET_SDA_IN();//切换为输入模式for(i = 0;i < 8; i ++){Delay_us(50);SCL = 0;Delay_us(50);//时钟线拉高 读数据保证对方数据不改变SCL = 1;//来一个延时保证电平可靠// Delay_us(5);//先左移接收变量,防止循环结束时改变该变量receive<<=1;//判断数据线电平if(SDAM){//高电平的话接收变量自加,低电平不变化只左移,即保证了该位为0receive++;}//延时一小会 保证一个可靠的电平// Delay_us(1);//时钟线拉低,允许下一位数据改变//SCL = 0;}Delay_us(50);SCL = 0;
//    if(!ack)
//    {//不需要应答 则给出非应答信号,不再继续
//       IIC_NAck();
//    }
//  else
//  {//需要应答 则给应答
//        IIC_Ack();
//    }return receive;
}void  Device_WriteData(uint8_t DeciveAddr,uint8_t DataAddr,uint8_t Data)
{//起始信号I2C_Start();    //发送器件地址                         IIC_Send_Byte(DeciveAddr);       //等待应答IIC_Wait_Ack();                          //发送数据地址IIC_Send_Byte(DataAddr);                     //等待应答IIC_Wait_Ack();                          //发送数据IIC_Send_Byte(Data);                     //等待应答IIC_Wait_Ack();                          //结束信号I2C_Stop();
}//读数据
//参数一 器件地址
//参数二 数据地址
//参数三 接收数据存储
//参数四 接收长度
//
void Decive_ReadData(uint8_t DeciveAddr,uint8_t DataAddr,uint8_t *ReciveData,uint8_t num)
{//定义计数变量uint8_t i;//起始信号I2C_Start();//发送器件地址IIC_Send_Byte(DeciveAddr);//等待应答IIC_Wait_Ack();//发送数据地址IIC_Send_Byte(DataAddr);                     //等待应答IIC_Wait_Ack();     //起始信号I2C_Start();//发送器件地址读模式IIC_Send_Byte(DeciveAddr + 1);//等待应答IIC_Wait_Ack();//读数据for(i = 0;i < (num-1);i ++){//前num-1位数据时需要给应答的因为要继续读*ReciveData= IIC_Read_Byte(1);ReciveData++;}//最后一位数据不需要给应答 因为不用读了*ReciveData = IIC_Read_Byte(0);//停止信号I2C_Stop();
}

注:I2C通讯需外接上拉电阻!

【STM8S103K3】 I2C相关推荐

  1. 【STM32】I2C相关函数和类型

    00. 目录 文章目录 00. 目录 01. I2C简介 02. 相关类型 03. 相关函数 04. 结构体封装 05. 预留 06. 附录 07. 声明 01. I2C简介 I2C(内部集成电路)总 ...

  2. 【STM32】I2C详解

    00. 目录 文章目录 00. 目录 01. I2C简介 02. I2C主要特性 03. I2C功能说明 04. I2C中断 05. I2C相关寄存器 5.1 I2C 控制寄存器 1 (I2C_CR1 ...

  3. Linux clock子系统【3】-i2c控制器打开时钟的流程分析(devm_clk_get)(consumer侧)

    文章目录 前言 一.硬件流程图 二.晶振设备树描述 三. I2CX时钟设备树描述 四.驱动中获得/使能时钟 4.1 流程源码分析 4.1.1 devm_clk_get(struct device *d ...

  4. 【转】 i2c驱动调试经验

    原文网址:http://blog.csdn.net/cmm20071020/article/details/7179958 把一个i2c驱动从2.6.21升级到2.6.39 上网查到一篇帖子,讲了驱动 ...

  5. 【InterFace】I2C 总线详述

    背景 昨天出去了一趟,人问:你熟悉什么?答:软硬件.结果,好尴尬. 硬件一般都做什么内容? 答:电源设计. 能说下升压.降压电路是怎么实现的吗? 答:不能.(Ps:后续增加 电源设计原理) 通讯都用到 ...

  6. 【RTT】I2C总线设备:分析

    I2C总线设备 概要 一.I2C硬件资源初始化 二.软件I2C的注册函数 三.I2C总线设备的注册 四.I2C总线设备的初始化 五.I2C的数据 六.I2C总线设备的使用 1. 查找I2C总线设备 2 ...

  7. 【sylixos】i2c设备驱动创建和使用

    前提是需要已实现过i2c总线驱动 步骤 步骤分为几步: 创建设备 API_I2cAdapterCreate 传输消息 API_I2cDeviceTransfer 发送消息 API_I2cDeviceM ...

  8. 【Arduino】I2C Master 实现

    #背景 前几天,有个海外的客户在使用 Arduino 连接产品(I2C接口)的时候,发现有异常.为了方便,我自己写了个 Arduino 的例程.使用 Arduino 例程的时候发现,官方的描述不太详细 ...

  9. 【单片机】I2C通信详解介绍(初学,浅显易懂,基本知识)

    介绍:I2C通讯协议(Inter-Integrated Circuit)引脚少,硬件实现简单,可扩展性强,不需要USART.CAN等通讯协议的外部收发设备,现在被广泛地使用在系统内多个集成电路(IC) ...

  10. 【STM32】I2C练习,HAL库读取MPU6050角度陀螺仪

    I2C练习 MPU6050简介 寄存器查询表格 STM32CubeMx配置 代码文件 mpu6050.h文件 mpu6050.c文件 main.c文件 总结 MPU6050简介 MPU-6000(60 ...

最新文章

  1. AI如何帮助我们理解意识——麻省理工最新大脑研究
  2. 发觉好像视力户籍变差么。。
  3. Unity中实现Hololens的三维空间映射Spatial mapping
  4. bartender外部表不是预期格式_三张表轻松搞定项目计划
  5. MPEG-LA发布VVC专利池
  6. Pythton3实例
  7. js获取对象数组中指定属性值对象_3分钟学会操作JavaScript内置对象,快来试试吧...
  8. centos 7 修改ip
  9. HDU 6051 If the starlight never fade(原根+推式子)
  10. 图解ZooKeeper的典型应用场景(转载)
  11. java8新特性有哪些
  12. 清华郝景芳:中国教育还欠缺什么?如何弥补当下教育的不足? (公号回复“郝景芳”下载PDF典藏版)
  13. 同济版《工程数学:线性代数》60条笔记全整理
  14. 元宇宙,风口还是扯淡?
  15. python爬虫获取维基百科词条
  16. 冬天洗衣不动手,这几款智慧洗衣机可以帮到你
  17. 被误解的明朝——中国的文艺复兴(转)
  18. 科学动画制作工具——Blender
  19. 联想禁止 win10 更新 v2.11 免费版
  20. arcgis区位图的制作——以武汉市为例

热门文章

  1. Linux程序设计 清空标准输入缓冲区
  2. Vue使用iconfont(阿里图标库)
  3. Java调用so文件
  4. CMMI3学习之路(一):在质疑与挣扎中偶然发现她竟是如此美丽
  5. TOGAF 企业连续系列
  6. python做购物系统的实训报告_网上购物系统实训总结
  7. CS229 笔记-1
  8. Selenium:鼠标、键盘事件
  9. MS17-010 补丁下载官方地址
  10. python下载安装教程(详细步骤+图示)