PIC单片机-普通IO口模拟I2C总线对24C02进行读写操作

2023-12-24 00:08

本文主要是介绍PIC单片机-普通IO口模拟I2C总线对24C02进行读写操作,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

使用PIC单片机的普通IO口模拟I2C总线,对24C02进行读写操作。其中,总线定义为:

#define       IIC_SCLK     RC3      //24C02时钟线
#define      IIC_SDAT     RC4      //24C02数据线

将跳线帽P11短接至24C02方向,将跳线帽P6段接至IIC方向。

I2C 总线协议规定任何将数据传送到总线的器件作为发送器,任何从总线接收数据的器件为接收器,数据传送是由产生串行时钟和所有起始停止信号的主器件控制的,主器件和从器件都可以作为发送器或接收器。

I2C 总线协议定义如下:

1、只有在总线空闲时才允许启动数据传送

2、在数据传送过程中当时钟线为高电平时数据线必须保持稳定状态不允许有跳变时钟线为高电平时数据线的任何电平变化将被看作总线的起始或停止信号

  • 起始信号:时钟线保持高电平期间数据线电平从高到低的跳变作为I2C 总线的起始信号。
  • 停止信号:时钟线保持高电平期间数据线电平从低到高的跳变作为I2C 总线的停止信号。
#include <htc.h>#define uint8 unsigned char
#define uint16 unsigned int__CONFIG(FOSC_HS &WDTE_OFF &BOREN_OFF &PWRTE_OFF &LVP_OFF); //设置配置位
//WDTE_OFF:disable watchdog timer       看门狗禁止
//LVP_OFF:low voltage programming disabled  低电压编程禁止
//FOSC_HS:high speed crystal/resonator  4M以上晶振选择HS高速
//PWRTDIS:disable power up timer
//BOREN_OFF:disable brown out reset/********************定义数据线************************************************/#define     IIC_SCLK    RC3     //24C02时钟线
#define     IIC_SDAT    RC4     //24C02数据线/********************定义全局变量**********************************************/
const uint8 disp[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90}; //0~9共阳数码管段码表
uint8 init[8] = {0x59, 0x43, 0x21, 0x11, 0x03, 0x03, 0x09, 0x00};           //EEPROM写初始值数组
uint8 recive[8];    //读EEPROM数据存放数组/********************函数声明**************************************************/void IIC_WriteACK(void);            //返回应答信号
void IIC_Stop(void);                //停止信号
void IIC_Writenoack(void);          //无应答信号
void IIC_Start(void);               //启动信号
void DelayUS(uint8 delay);          //微妙延时
void DelayMS(uint16 delay);         //毫秒延时
uint8 IIC_ReadByte(void);           //IIC读8位字节数据
uint8 IIC_WriteByte(uint8 data);    //IIC写8位字节数据
void Display(uint8 chosebit, uint8 data);
void IIC_Read_Mulit_Data(uint8 commond, uint8 address, uint8 *addrpoint, uint8 bytenum);
void IIC_Write_Mulit_Data(uint8 commond, uint8 reg_addr, uint8 *mdatapointer, uint8 bytenum);/*******************************************************************************
* 函 数 名: DelayUS(uint8 delay)
* 函数功能: 微秒延时    for 20MHZ
* 入口参数: delay
* 返    回: 无
*******************************************************************************/void DelayUS(uint8 delay)
{
    while(--delay);
}/*******************************************************************************
* 函 数 名: DelayMS(uint16 delay)
* 函数功能: 毫秒延时    for20MHZ
* 入口参数: delay
* 返    回: 无
*******************************************************************************/void DelayMS(uint16 delay)
{
    uint16 i;
    for(; delay > 0; delay--)
        for(i = 0; i < 453; i++);
}/******************************************************************************
* 函 数 名: IIC_WriteACK(void)
* 函数功能: 从机接收数据正常时,向主机发送应答信号
* 入口参数: 无
* 返    回: 无
*******************************************************************************/void IIC_WriteACK(void)
{
    IIC_SDAT = 0;           //拉低数据线,给主机发送一个低电平
    IIC_SCLK = 1;           //时钟有效,发送数据
    IIC_SCLK = 0;
    //    IIC_SDAT = 1;
}/******************************************************************************
* 函 数 名: IIC_Writenoack(void)
* 函数功能: 从机接收数据结束时,向主机发送无应答信号
* 入口参数: 无
* 返    回: 无
*******************************************************************************/void IIC_Writenoack(void)
{
    IIC_SCLK = 0;
    IIC_SDAT = 1;         //发送高电平,表示无应答
    IIC_SCLK = 1;         //时钟有效
    IIC_SCLK = 0;
}/******************************************************************************
* 函 数 名: IIC_Start(void)
* 函数功能: 启动EEPROM读写操作
* 入口参数: 无
* 返    回: 无
*******************************************************************************/void IIC_Start(void)
{
    IIC_SDAT = 1;         //数据线置位
    IIC_SCLK = 1;         //时钟有效
    IIC_SDAT = 0;         //数据线复位,在时钟有效期间,数据线产生一个下降沿表示启动EEPROM读写操作
    IIC_SCLK = 0;         //时钟无效
}/******************************************************************************
* 函 数 名: IIC_Stop(void)
* 函数功能: 停止对EEPROM读写操作
* 入口参数: 无
* 返    回: 无
*******************************************************************************/void IIC_Stop(void)
{
    IIC_SDAT = 0;         //数据线复位
    IIC_SCLK = 1;         //时钟有效
    IIC_SDAT = 1;         //数据线复位
    IIC_SCLK = 0;         //数据线置位,在时钟有效期间,数据线产生一个上升沿表示停止EEPROM读写操作
}/******************************************************************************
* 函 数 名: IIC_WriteByte(uint8 wdata)
* 函数功能: 进行8位字节数据写操作
* 入口参数: wdata待写数据
* 返    回: status:0:成功 1:失败
*******************************************************************************/
uint8 IIC_WriteByte(uint8 wdata)
{
    uint8 i, status;
    IIC_SCLK = 0;                   //时钟无效
    for(i = 0; i < 8; i++)              //写8位字节数据
    {
        if((wdata & 0x80) == 0x80)  //读最高位数据
        {
            IIC_SDAT = 1;
        }
        else
        {
            IIC_SDAT = 0;
        }
        IIC_SCLK = 1;           //时钟有效
        wdata <<= 1;            //数据左移一位
        NOP();
        IIC_SCLK = 0;
    }    TRISC4 = 1;         //数据线设置为输入模式
    IIC_SDAT = 1;       //拉高数据线
    NOP();
    IIC_SCLK = 1;       //时钟有效
    NOP();
    if(IIC_SDAT)        //第九个时钟数据为1,则写失败成功,IIC器件没有应答
    {
        status = 1;
    }
    else
    {
        status = 0;
    }
    IIC_SCLK = 0;
    TRISC4 = 0;         //数据线设置回输出模式
    return status;      //返回写成功与否状态
}/******************************************************************************
* 函 数 名: IIC_WriteData(uint8 commond,uint8 reg_addr,*mdatapointer,uint8 bytenum)
* 函数功能: 写多字节数据
* 入口参数: commond:读写指令,reg_addr写操作地址,mdata待写数据,bytenum字节数
* 返    回: 无
*******************************************************************************/
void IIC_Write_Mulit_Data(uint8 commond, uint8 reg_addr, uint8 *mdatapointer, uint8 bytenum)
{
    uint8 i, status;
    IIC_Start();    //启动IIC
    status = IIC_WriteByte(commond);    //写器件地址
    if(!status)
    {
        status = IIC_WriteByte(reg_addr);   //写寄存器地址
    }
    for(i = 0; i < bytenum; i++)
    {
        if(!status)
        {
            status = IIC_WriteByte(*(mdatapointer + i));        //写数据
        }
    }
    IIC_Stop();     //结束IIC
}/******************************************************************************
* 函 数 名: IIC_ReadByte(void)
* 函数功能: 8位数据读操作
* 入口参数: 无
* 返    回: bytedata读取的8位数据
*******************************************************************************/
uint8 IIC_ReadByte(void)
{
    uint8 i, bytedata;
    TRISC4 = 1;     //数据线设置为输入模式
    IIC_SDAT = 1;   //数据线拉高
    IIC_SCLK = 0;
    for(i = 0; i < 8; i++)      //读8位数据
    {
        IIC_SCLK = 1;
        bytedata <<= 1;
        bytedata |= IIC_SDAT;
        IIC_SCLK = 0;
        NOP();
    }
    TRISC4 = 0;     //数据线设置回输出模式
    return(bytedata);//返回数据
}/******************************************************************************
* 函 数 名: IIC_Read_Mulit_Data(uint8 commond,uint8 address,uint8 *addrpoint,uint8 bytenum)
* 函数功能: 对IIC行进多字节读操作
* 入口参数: commond地址读写命令,address读数据的起始地址,addrpoint数据存放地址指针,bytenum字节数
* 返    回: 无
*******************************************************************************/void IIC_Read_Mulit_Data(uint8 commond, uint8 address, uint8 *addrpoint, uint8 bytenum)
{
    uint8 i, status;
    IIC_Start();                        //启动EEPROM读写操作
    status = IIC_WriteByte(commond);     //写从机地址及写操作指令
    if(!status)
    {
        status = IIC_WriteByte(address);    //写寄存器地址
    }
    if(!status)
    {
        IIC_Start();    //重新启动IIC
        status = IIC_WriteByte(commond + 0x01); //写读指令
    }
    for(i = 0; i < bytenum; i++)
    {
        if(!status)
        {
            addrpoint[i] = IIC_ReadByte();  //读取数据存放到数组
            if(i < (bytenum - 1))
            {
                IIC_WriteACK();             //返回应答信号
            }
            else
            {
                IIC_Writenoack();           //读完最后一个数据返回无应答信号,表示结束读操作
            }
        }
    }
    IIC_Stop();                     //停止EEPROM读写操作
    DelayUS(1);
}/*******************************************************************************
* 函 数 名: LED_Display(uint8 chosebit,uint8 wdata)
* 函数功能: 单个数码管显示
* 入口参数: chosebit选择字位,wdata字型
* 返    回: 无
*******************************************************************************/void LED_Display(uint8 chosebit, uint8 wdata)
{
    if((chosebit < 0) || (chosebit > 4))
        return;
    ADCON1 = 0x86;  //10000110  PORTA口设置为数字IO口
    TRISA &= 0x00;
    TRISE &= 0xEF;      //配置PORTD为普通IO口,对PORTD的操作务必加上这句
    TRISD = 0x00;       //数据线配置为输出
    PORTA = (PORTA & 0xE3) | ((chosebit + 3) << 2); //RA2:RA3:RA4:011 选通第一位 100选通第二位 101选通第三位 110选通第四位
    PORTD = wdata;  //送显示数字的断码
    DelayUS(100);       //延时
    PORTD = 0xFF;       //关闭显示
}/******************************************************************************
* 函 数 名: main(void)
* 函数功能: 利用普通IO口模拟IIC总线,对24C02写8字节数据,并读取8个字节数据
* 入口参数: 无
* 返    回: 无
*******************************************************************************/void main(void)
{
    TRISC3 = 0;             //配置时钟线为输出
    TRISC4 = 0;             //配置数据线为输出
    IIC_Write_Mulit_Data(0xa0, 0x00, init, 8);  //写8字节数据
    DelayMS(5);
    while(1)
    {
        IIC_Read_Mulit_Data(0xa0, 0x00, recive, 8); //读8字节数据
        LED_Display(0, disp[init[0] / 16]); //显示要被写入的值
        LED_Display(1, disp[init[0] % 16]);
        LED_Display(2, disp[recive[0] / 16]);   //显示从AT2402读到的值
        LED_Display(3, disp[recive[0] % 16]);
        DelayMS(1);
    }
}

这篇关于PIC单片机-普通IO口模拟I2C总线对24C02进行读写操作的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/529938

相关文章

51单片机学习记录———定时器

文章目录 前言一、定时器介绍二、STC89C52定时器资源三、定时器框图四、定时器模式五、定时器相关寄存器六、定时器练习 前言 一个学习嵌入式的小白~ 有问题评论区或私信指出~ 提示:以下是本篇文章正文内容,下面案例可供参考 一、定时器介绍 定时器介绍:51单片机的定时器属于单片机的内部资源,其电路的连接和运转均在单片机内部完成。 定时器作用: 1.用于计数系统,可

mysql索引一(普通索引)

mysql的索引分为两大类,聚簇索引、非聚簇索引。聚簇索引是按照数据存放的物理位置为顺序的,而非聚簇索引则不同。聚簇索引能够提高多行检索的速度、非聚簇索引则对单行检索的速度很快。         在这两大类的索引类型下,还可以降索引分为4个小类型:         1,普通索引:最基本的索引,没有任何限制,是我们经常使用到的索引。         2,唯一索引:与普通索引

零基础STM32单片机编程入门(一)初识STM32单片机

文章目录 一.概要二.单片机型号命名规则三.STM32F103系统架构四.STM32F103C8T6单片机启动流程五.STM32F103C8T6单片机主要外设资源六.编程过程中芯片数据手册的作用1.单片机外设资源情况2.STM32单片机内部框图3.STM32单片机管脚图4.STM32单片机每个管脚可配功能5.单片机功耗数据6.FALSH编程时间,擦写次数7.I/O高低电平电压表格8.外设接口

大语言模型(LLMs)能够进行推理和规划吗?

大语言模型(LLMs),基本上是经过强化训练的 n-gram 模型,它们在网络规模的语言语料库(实际上,可以说是我们文明的知识库)上进行了训练,展现出了一种超乎预期的语言行为,引发了我们的广泛关注。从训练和操作的角度来看,LLMs 可以被认为是一种巨大的、非真实的记忆库,相当于为我们所有人提供了一个外部的系统 1(见图 1)。然而,它们表面上的多功能性让许多研究者好奇,这些模型是否也能在通常需要系

Python应用开发——30天学习Streamlit Python包进行APP的构建(9)

st.area_chart 显示区域图。 这是围绕 st.altair_chart 的语法糖。主要区别在于该命令使用数据自身的列和指数来计算图表的 Altair 规格。因此,在许多 "只需绘制此图 "的情况下,该命令更易于使用,但可定制性较差。 如果 st.area_chart 无法正确猜测数据规格,请尝试使用 st.altair_chart 指定所需的图表。 Function signa

气象站的种类和应用范围可以根据不同的分类标准进行详细的划分和描述

气象站的种类和应用范围可以根据不同的分类标准进行详细的划分和描述。以下是从不同角度对气象站的种类和应用范围的介绍: 一、气象站的种类 根据用途和安装环境分类: 农业气象站:专为农业生产服务,监测土壤温度、湿度等参数,为农业生产提供科学依据。交通气象站:用于公路、铁路、机场等交通场所的气象监测,提供实时气象数据以支持交通运营和调度。林业气象站:监测林区风速、湿度、温度等气象要素,为林区保护和

企业如何进行员工的网络安全意识培训?

企业网络安全意识培训的重要性         企业网络安全意识培训是提升员工网络安全素质的关键环节。随着网络技术的快速发展,企业面临的网络安全威胁日益增多,员工的网络安全意识和技能水平直接关系到企业的信息安全和业务连续性。因此,企业需要通过系统的网络安全意识培训,提高员工对网络安全的认识和防范能力,从而降低企业在面对潜在安全风险时的损失和影响。 企业网络安全意识培训的方法         企

基于 Java 实现的智能客服聊天工具模拟场景

服务端代码 import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;public class Serv

WDF驱动开发-WDF总线枚举(一)

支持在总线驱动程序中进行 PnP 和电源管理 某些设备永久插入系统,而其他设备可以在系统运行时插入和拔出电源。 总线驱动 必须识别并报告连接到其总线的设备,并且他们必须发现并报告系统中设备的到达和离开情况。 总线驱动程序标识和报告的设备称为总线的 子设备。 标识和报告子设备的过程称为 总线枚举。 在总线枚举期间,总线驱动程序会为其子 设备创建设备对象 。  总线驱动程序本质上是同时处理总线枚

使用JWT进行安全通信

在现代Web应用中,安全通信是至关重要的。JSON Web Token(JWT)是一种流行的安全通信方式,它允许用户和服务器之间安全地传输信息。JWT是一种紧凑的、URL安全的表示方法,用于在两方之间传输信息。本文将详细介绍JWT的工作原理,并提供代码示例帮助新人理解和实现JWT。 什么是JWT? JWT是一种开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间以JSO