打印
[STM32G0]

再谈STM32CUBE之硬SPI驱动0.96_OLED

[复制链接]
600|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
GlenX|  楼主 | 2022-11-3 09:54 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
OLED坛子里最多的就是SPI,但大都是PIN仿真的SPI,当然主要是有很多教程之类的开源。
比较难找的例程是STM32CUBE硬件SPI例程,即便是有,也都不能简单“移植”。
本人经过反复试验,曾也认为STM32CUBE甚至STM的硬件SPI/IIC不好用,或者对于LCD和OLED不可用。
经反复试验,终于发现了几个小问题,分享给大家:
1.很多SPI的系统甚至STM本身默认是没有上拉电阻的:
    无论STM是主站还是从站,SPI网络中只要没有上拉,就无法通讯!
    这是最大的坑,你会以为硬件自动配置的系统就符合“SPI”要求,其实不然,是需要根据硬件的布局合理设置上拉的。
    当然,试验或开发板可以采用内部上拉实现(后来我就是是这样做的)。
2.你认为SPI默认的通讯速度一般都能适应大部分的通讯,其实不然,需要查阅,很多都只能支持到2M。而默认的在20M以上,所以就无法实现通讯。
下面就分享我重点修改的地方,其他函数等内容“移植”就可以了:

1)管脚定义,这里我用的是SPI1。

2)SPI通讯速度修改

3)重点函数修改
void OLED_WrDat(u8 data)
{
        OLED_DC_SET();                // DC = 1
           while(HAL_SPI_Transmit(&hspi1,&data, 0X01 ,0xFF) != HAL_OK)
        {
                HAL_Delay(1);
        }
}
void OLED_WrCmd(u8 cmd)
{
        OLED_DC_CLR();                // DC = 0
        while(HAL_SPI_Transmit(&hspi1,&cmd, 0X01 ,0x1FF) != HAL_OK)
        {
                HAL_Delay(1);
        }
}

4)其他函数都是“移植”的,经过上面修改就都可以用了。

使用特权

评论回复
沙发
软核硬核| | 2022-11-3 14:21 | 只看该作者
这移植是真快,所以说包装成库是非常重要得!

使用特权

评论回复
板凳
hwboy05| | 2023-2-3 00:35 | 只看该作者
我这几天在调STM32G030C8T6的硬件SPI1碰到了问题,SPI_SCK和SPI_MOSI没有信号输出,请帮忙看看,谢谢。
#define SPI_RX_MODE 0
#define SPI_TX_MODE 1
#define LCD_CS      'A',4
#define LCD_SCK     'A',5
#define LCD_SDA     'A',7
#define LCD_CD      'A',6
#define LCD_RST     'B',0
void GPIO_Config(UCHAR port,UCHAR pin,UCHAR mode,UCHAR altfun,UCHAR speed,UCHAR od,UCHAR pull,UCHAR level);

void SPI1_Init(void)
{
    RCC->IOPENR |= 0x1;             //Enable GPIO A Clock
    GPIO_Config(LCD_CS, GPIO_OutputMode, GPIO_AF0, GPIO_SpeedMedium, GPIO_PushPull, GPIO_PullNo, 1);
    GPIO_Config(LCD_SDA, GPIO_AltFunMode, GPIO_AF0, GPIO_SpeedMedium, GPIO_OD, GPIO_PullNo, 1);
    GPIO_Config(LCD_SCK, GPIO_AltFunMode, GPIO_AF0, GPIO_SpeedMedium, GPIO_OD, GPIO_PullNo, 1);
    RCC->APBENR2 |= 0x1000;         //Enable SPI1 Clock
    Delay(0x100);
    RCC->APBRSTR2 |= 0x1000;        //Reset SPI1
    Delay(0x100);
    RCC->APBRSTR2 &= 0xffffefff;    //Release Reset SPI1
    Delay(0x100);
    SPI1->CR1 = 0xc324;             //Bidi mode, Output enable, BaudRate=PCLK/32=2.25M, Master, PHASE0
    SPI1->CR2 = 0x1700;             //FIFO threshold: 8bit, Data size: 8bit, Motorola mode
    SPI1->CR1 |= 0x40;              //SPI enable
}

void SPI1_Dir_Sel(u8 mode)
{
    if(SPI_RX_MODE==mode)
    {
        SPI1->CR1 &= 0xbfff;
    }
    else        //TX mode
    {
        SPI1->CR1 |= 0x4000;
    }
}

u8 TFT_WR(u8 cmd, u8 *txdat, u16 len)
{
    u8 i;
    u16 cnt;
    ClrPin(LCD_CS);
    ClrPin(LCD_CD); //command
    /*cnt=0xffff;
    while((SPI1->SR)>=0xfff && cnt--);      //wait for TX FIFO empty
    if(0==cnt)
    {
        SetPin(LCD_CS);
        return FAIL;
    }*/
    SPI1->DR=cmd;   //send command
    Delay(20);
    SetPin(LCD_CD); //data
    for(i=0;i<len;i++)
    {
        /*cnt=0xffff;
        while((SPI1->SR)>=0xfff && cnt--);  //wait for TX FIFO empty
        if(0==cnt)
        {
            SetPin(LCD_CS);
            return FAIL;
        }*/
        Delay(20);
        SPI1->DR=*(txdat+i);
    }
    SetPin(LCD_CS);
    return OK;
}


u8 TFT_RD(u8 cmd, u8 *rxbuf, u16 len)
{
    u8 i;
    u16 cnt;
    /*cnt=0xffff;
    while((SPI1->SR)>=0xfff && cnt--);     //wait for TX FIFO empty
    if(0==cnt)
    {
        return FAIL;
    }*/
    ClrPin(LCD_CS);
    ClrPin(LCD_CD); //command
    Delay(0x100);
    SPI1->DR=cmd;                           //send read command
    /*while((SPI1->SR) & 0x600)               //wait untill RX FIFO empty
    {
        i=(u8)(SPI1->DR);
    }*/
    Delay(80);
    SPI1_Dir_Sel(SPI_RX_MODE);              //change direction for RX
    SetPin(LCD_CD); //data
    for(i=0;i<len;i++)
    {
        /*cnt=0xffff;
        while((SPI1->SR)>=0xfff && cnt--);  //wait for FIFO empty
        if(0==cnt)
        {
            SetPin(LCD_CS);
            SPI1_Dir_Sel(SPI_TX_MODE);      //change direction for TX(default)
            return FAIL;
        }*/
        Delay(80);
        SPI1->DR=0;
        *(rxbuf+i)=SPI1->DR;
    }
    SetPin(LCD_CS);
    SPI1_Dir_Sel(SPI_TX_MODE);              //change direction for TX(default)
    return OK;
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

15

主题

529

帖子

2

粉丝