找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1638|回复: 5
收起左侧

PIC18F4680单片机SPI和IIC可以分时复用吗?

[复制链接]
ID:1083396 发表于 2023-6-15 15:00 | 显示全部楼层 |阅读模式
PIC18f4680  SPI和IIC同时使用,SPI 驱动字库芯片,IIC驱动OLED。SPI和IIC都是使用的RC3 和RC4引脚,可以进行分时复用吗?怎么实现?

这是4680引脚图

这是4680引脚图
void main(void)
{
    unsigned char NixieNum =0 ,Temp1 = 0;
    GPIO_Init();
    Timer0_int();
    OLED_Init();
    OLED_Clear(0xf0);
    OLED_Clear(0x00);
    OLED_Clear(0x0F);
    OLED_Clear(0x00);
    OLED_ShowString(1,1,"KeyNum:");
    OLED_ShowString(2,1,"Nixie:");
    OLED_ShowString(3,1,"0x");
//    OLED_GB2312_15x16_ShowChar(4,1,"按键");
  while(1)
  {
      NixieNum = Key_NIXIE_Num();
      if(NixieNum)
      {
         Temp1 = NixieNum;
         OLED_ShowBinNum(2,8,Temp1,8 );
         OLED_ShowHexNum(3,3,Temp1,2);
         if(Temp1 == 0xDF){ LED_RGB_G_ON();}
         if(Temp1 == 0xEF){ LED_RGB_B_ON();}
         if(Temp1 == 0xF7){ LED_RGB_R_ON();}
         if(Temp1 == 0x5F){ LED_RGB_G_OFF();}
         if(Temp1 == 0x6F){ LED_RGB_B_OFF();}
         if(Temp1 == 0x77){ LED_RGB_R_OFF();}
      }

   }
}




void IIC_Init(void)
{
    LATCbits.LC0 = 1;             //SPI_CS_PIN          LATCbits.LC0(字库片选)
    TRISCbits.RC0 = 0;             //CS  1:输入   0:输出(字库片选)
    /*********************************
      **** 硬件IIC   GPIO初始化****
    *********************************/
    LATCbits.LC3 = 0;             //IIC_SCL
        LATCbits.LC4 = 0;             //IIC_SDA     

        TRISCbits.RC3 = 1;             //设置为输入
        TRISCbits.RC4 = 1;             //设置为输入
    SSPSTAT = 0x80;         //设置通讯速率100K;Disable SMBus
    SSPCON1 = 0x38;         //使能串口,主控模式,时钟=Fosc/(4*(SSPADD+1)
    SSPCON2 = 0x00;         //
    PIR1bits.SSPIF=0;       //中断标志清零
    SSPADD = 0x27;         // 频率 = Focs/(4 * (SSPADD + 1))   ;100K频率 16M晶振 SSPADD= 0x27;                        
}



void  SPI_Init(void)
{
     /*********************************
      **** SPI__GPIO初始化****
    *********************************/
    LATCbits.LC0 = 1;             //SPI_CS_PIN          LATCbits.LC0(字库片选)
    LATCbits.LC2 = 1;             //SPI_CS_PIN          LATCbits.LC0(FLASH片选)
        LATCbits.LC3 = 0;             //SPI_SCK_PIN          LATCbits.LC3
        PORTCbits.RC4 = 0;            //SPI_MISO_PIN         PORTCbits.RC4       //数据输入
        LATCbits.LC5 = 0;             //SPI_MOSI_PIN         LATCbits.LC5                //数据输出

        TRISCbits.RC0 = 0;             //CS  1:输入   0:输出(字库片选)
    TRISCbits.RC2 = 0;             //flash_CS  1:输入   0:输出(FLASH片选)
        TRISCbits.RC3 = 0;             //CLK 1:输入   0:输出
        TRISCbits.RC4 = 1;             //SDI 1:输入   0:输出               
        TRISCbits.RC5 = 0;             //SDO 设置RC5端口为输出

    //SCLK开始高电平上升沿发送数据,下降沿接收数据。
     //0000 0000      
        SSPSTAT = 0x80;   //bit7 = 1; 0:在数据输出时间的中间采样输入数据 1:在数据输出时间的末端采样输入数据
                      //bit6 = 0; 0:时钟状态从空闲换到有效时发送     1:时钟从有效换到空闲时发送
                      //bit0 = 0; 接收未完成,SSBUF空
        SSPCON1 = 0x32;    //bit5 = 1; 使能SPI, bit4 = 1;空闲状态时,时钟为高电平
                       //bit3-0 = 0010,SPI主控模式,时钟=Fosc/64
//    SSPCON1bits.WCOL  = 0;          //写冲突检测 0:未发生冲突  1:
//    SSPCON1bits.CKP   = 1;          //bit4 = 1;空闲状态时,时钟为高电平
//    SSPCON1bits.SSPM3 = 0;          //bit3-0 = 0011,SPI主控模式,时钟=TMR2输出/2
//    SSPCON1bits.SSPM2 = 0;          //         0010,SPI主控模式,时钟=Fosc/16
//    SSPCON1bits.SSPM1 = 1;          //         0001,SPI主控模式,时钟=Fosc/16
//    SSPCON1bits.SSPM0 = 0;          //         0000,SPI主控模式,时钟=Fosc/4

    SSPIF = 0;             //中断标志位清零
    SSPCON1bits.SSPEN = 1;          //使能SPI

}


/**
  * @brief  OLED写命令
  * @param  Command 要写入的命令
  * @retval 无
  */
void oled_cmd(char cmd)
{
    IIC_Init();
    IIC_STAT();
    IIC_SendByte(0x78);
    IIC_SendByte(0x00);
    IIC_SendByte(cmd);
    IIC_STOP();
}
/**
  * @brief  OLED写数据
  * @param  Data 要写入的数据
  * @retval 无
  */
void oled_data(char Data)
{
    IIC_Init();
    IIC_STAT();
    IIC_SendByte(0x78);
    IIC_SendByte(0x40);
    IIC_SendByte(Data);
    IIC_STOP();
}


/**
  * @brief  OLED显示汉字
  * @param  Line 行位置,范围:1~4
  * @param  Column 列位置,范围:1~16
  * @param  text 要显示的一个字符,范围:字库芯片
  * @retval 无
  */
void OLED_GB2312_15x16_ShowChar(unsigned char Line, unsigned char Column, unsigned char *text)
{              
        unsigned char i,j;
        unsigned char SZHPArray[32];
        unsigned char HZHPArray[32];
        while(*text != 0)
        {
    //    SPI_Init();
                GT30L32S4W_Get_Bytes_GB2312_15x16(text,HZHPArray);
                GB2312_15x16_HengZhiHengPai_to_ShuZhiHengPai(SZHPArray,HZHPArray);
        //        IIC_Init();
                for(j = 0; j < 32; j ++)
                {
                        OLED_SetCursor((unsigned char)((Line - 1) * 2), (unsigned char)((Column - 1) * 8));                //设置光标位置在上半部分
                        for (i = 0; i < 16; i++)
                        {
                                oled_data(SZHPArray[ i]);                        //显示上半部分内容
                        }
                        OLED_SetCursor((unsigned char)((Line - 1) * 2 + 1), (unsigned char)((Column - 1) * 8));        //设置光标位置在下半部分
                        for (i = 0; i < 16; i++)
                        {
                                oled_data(SZHPArray[i + 16]);                //显示下半部分内容
                        }
                }
                text += 2;        //下个字
                Column += 2;
        }
}




IIC初始化

IIC初始化

SPI

SPI

SPI

SPI
OLED.png
回复

使用道具 举报

ID:1083396 发表于 2023-6-15 15:04 | 显示全部楼层
我应该在程序的什么地方进行分时复用?没有思路
回复

使用道具 举报

ID:155507 发表于 2023-6-15 19:25 | 显示全部楼层
对于PIC18F4680单片机来说,SPI和I2C(IIC)是两种不同的串行通信协议,它们不能直接分时复用在同一个引脚上。

SPI(Serial Peripheral Interface)是一种同步的串行通信协议,需要使用SCK(时钟)、SDI(数据输入)、SDO(数据输出)和SS(片选)等引脚进行通信。SPI通信是基于主从设备的方式进行的,主设备控制通信时序和数据传输。

I2C(Inter-Integrated Circuit,也称为IIC)是一种双线制串行通信协议,需要使用SCL(时钟)和SDA(数据)等引脚进行通信。I2C通信是基于主从设备的方式进行的,主设备控制通信时序和数据传输。

由于SPI和I2C使用不同的通信方式和时序,它们不能直接在同一个引脚上进行分时复用。每个通信协议都需要专用的引脚来进行通信。

如果您需要同时使用SPI和I2C通信,您需要为每个通信协议分配不同的引脚,并根据需要进行引脚的连接和配置。

SPI 设备可以通过不声明其从机选择来忽略 SCK 和 SDI,但是 IIC 设备会被 SCL 和 SDA 线上的正常 SCK 和 SDI 信号弄糊涂。 即使粗略地看一下 IIC 规范也会发现这一点。

回复

使用道具 举报

ID:1083396 发表于 2023-6-16 10:25 | 显示全部楼层
angmall 发表于 2023-6-15 19:25
对于PIC18F4680单片机来说,SPI和I2C(IIC)是两种...

"【解惑帖】I2C与SPI总线分时复用造成的冲突",这个帖子上说可以分时复用。我也认为是可以的只要在使用SPI时关闭IIC,在使用IIC时关闭SPI应该就能实现。我再研究研究。谢谢
回复

使用道具 举报

ID:123289 发表于 2023-6-16 11:32 | 显示全部楼层
你可以相像一下:
在时间1,将它配制成SPI,这一点CPU会无条件服从。
在时间2,再将它配制成I2C,这一点CPU也无法抗拒啊。
所以你的想法是成立的!
不过,你要想好,通讯的对方是否可以配合,以及外部分硬件是否能够配合。
回复

使用道具 举报

ID:1083396 发表于 2023-6-16 11:58 | 显示全部楼层
yzwzfyz 发表于 2023-6-16 11:32
你可以相像一下:
在时间1,将它配制成SPI,这一点CPU会无条件服从。
在时间2,再将它配制成I2C,这一点C ...

对的理论上是这样的。
现在是IIC驱动的OLED显示没有问题,SPI控制的字库读不出。

SPI控制的字库,在片选选通之前,将通讯切换成SPI理论上应该可以。
我感觉是MSSP中的哪个寄存器没有配置对。或者是配置的顺序不对。
单独测试SPI和IIC都是没有问题的
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表