以下为.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 #include #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 0000 SDA=1; else SDA=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) { //高电平的话接收变量自加,低电平不变化只左移,即保证了该位为0 receive++; } //延时一小会 保证一个可靠的电平 // 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通讯需外接上拉电阻!
上一篇:瑞萨电子推出32位RX671 MCU,实现高性能和高能效
下一篇:东芝推出TXZ+TM族高级系列基于Arm® Cortex®-M4的新款M4G组MCU
推荐阅读
史海拾趣
为了提高生产效率和产品质量,Alpha Industries决定引入数字化生产线。通过与电子设备制造商合作,公司成功建立起一条自动化生产线,实现了从设计到生产的无缝对接。数字化生产线的建立不仅提高了生产效率,还降低了生产成本,使得Alpha Industries的产品更具市场竞争力。
随着电子技术的飞速发展,军事装备也在不断升级。Alpha Industries敏锐地捕捉到了这一趋势,开始将电子技术应用于其军事服装设计中。例如,公司研发了一款带有GPS定位功能的飞行夹克,帮助飞行员在复杂环境中快速定位。此外,Alpha Industries还利用电子传感器技术,开发出能够监测士兵体温和心率的战地风衣,为军队提供更为全面的保障。
在电子行业的发展过程中,Continental Industries注重与其他企业的合作与共赢。公司与多家知名企业建立了长期稳定的合作关系,共同开展技术研发和产品创新。通过资源共享和优势互补,双方实现了互利共赢,共同推动了电子行业的进步。
在追求经济效益的同时,BCD Semi(Diodes)公司也积极履行企业社会责任,关注可持续发展。公司严格遵守环保法规,采用环保材料和工艺,减少生产过程中的污染排放。同时,公司还积极参与社会公益事业,为当地社区的发展做出贡献。这些举措不仅提升了公司的社会形象,也为公司的可持续发展奠定了坚实基础。
请注意,以上故事是基于电子行业的一般情况和BCD Semi(Diodes)公司的行业地位构建的,并非真实发生的历史事件。如需了解BCD Semi(Diodes)公司的真实发展故事,建议查阅公司官方发布的资料或相关新闻报道。
随着电子行业的快速发展,Barry Industries Inc意识到只有不断创新才能在市场中立足。公司加大了对研发的投入,引进了一批高素质的研发人才,并建立了完善的研发体系。经过多年的努力,Barry成功突破了微波半导体封装技术的多项关键技术,推出了多款性能卓越、具有创新性的产品。这些产品不仅广泛应用于军事、航天、通信等领域,还为公司赢得了市场的广泛认可。
随着电子行业的快速发展和市场竞争的加剧,Dolphin Interconnect Solutions ASA面临着前所未有的挑战。为了应对这些挑战,公司积极调整战略方向,加大在人工智能、物联网等新兴领域的投入。同时,Dolphin还加强了与产业链上下游企业的合作,共同推动产业链的转型升级。这些努力使得Dolphin在激烈的市场竞争中保持了稳健的发展态势。
麻烦各位了,小弟新手,有几个问题在这里求教: 1.wince自带手写识别软件不能识别简体,请问怎样做才能让它识别简体? 2.如果要编写一个自己的识别软件,难度大吗?编写的大概步骤是什么?(希望能 比帮助文档具体一点)恳请赐告!谢谢 … 查看全部问答∨ |
in [求助] 中, 换了一个电源带来的问题 我的问题这样的, 主机只是简单的扫描端口, 子机负责把信息显示出来(用LED),开机时会读取一下EEPROM中字符,总共才20个字符。 原来我用子机的电源,主机的电源也是从子机那里拉过来的,很正常,也很 ...… 查看全部问答∨ |
本帖最后由 paulhyde 于 2014-9-15 09:47 编辑 传闻今年没有无线通信题目了,不知是否属实。 如果真的没有了,以前做无线通信的该怎么准备呢? … 查看全部问答∨ |
ARM启动代码学习(一)RO和RW还有ZI代表什么?(转载) 一般而言,一个程序包括只读的代码段和可读写的数据段。在ARM的集成开发环境中,只读的代码段和常量被称作RO段(ReadOnly);可读写的全局变量和静态变量被称作RW段(ReadWrite);RW段中要被初始化为零的变量被称为ZI段(ZeroInit) ...… 查看全部问答∨ |
ti5402的端口地址在哪找呢,手册里没发现呀。 ioport unsigned int port8FEE; 这句话后面的8FEE是在哪找的呀 我在手册上找不到 … 查看全部问答∨ |
找了capsense的例程,试着做了capsense控制led的工程。 功能介绍: 用手滑动capsense的触摸板,实现led颜色的改变。 具体连接: 下一步: 利用自带的放大器,完成模拟信号的放大滤波处理。… 查看全部问答∨ |