打印
[其他ST产品]

STM32F030使用硬件SPI与字库芯片通信

[复制链接]
150|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
舒伯特玫瑰|  楼主 | 2022-12-31 19:22 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
STM32F030使用硬件SPI与字库芯片通信

前言
在淘宝买了350-019-PC 3.5寸TFT彩屏,卖家提供了DEMO程序是软件模拟SPI的,但这种程序只能用于演示,实际使用其通讯速率远远不能够满足要求。因此在转换为STM32自带的SPI通讯的时候,ST7796S驱动由于是只发送不接受,因此很快就能够调通,但是模块上的字库芯片是就调试了好几天都一直无法调通,网上也查询了很多资料依然无法解决,最后是给询问我同事之后才终于解决,最后才知道我对硬件SPI有有误解才导致了这次的问题,为了让自己长记性,因此写了这个博文。

基本信息

单 片 机: STM32F030C8Tx
通信接口:SPI2
字库芯片:JLX-GB2312-3205


使用特权

评论回复
评论
舒伯特玫瑰 2022-12-31 19:27 回复TA
———————————————— 版权声明:本文为CSDN博主「Flame.Zheng」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/shaoxin02/article/details/122160479 
沙发
舒伯特玫瑰|  楼主 | 2022-12-31 19:23 | 只看该作者
SPI的代码
void SPI2_init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    SPI_InitTypeDef   SPI_InitStructure;

        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
       
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF ;
        GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
        GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_Level_3;
        GPIO_Init(GPIOB, &GPIO_InitStructure);

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_0);
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_0);
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_0);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;   
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;  
    GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    SPI_I2S_DeInit(SPI2);
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;   
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;  
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;   
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;   
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;   
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitStructure.SPI_CRCPolynomial = 7;
    SPI_Init(SPI2, &SPI_InitStructure);

    SPI_RxFIFOThresholdConfig(SPI2, SPI_RxFIFOThreshold_QF);
    SPI_Cmd(SPI2, ENABLE);
}

void SPI2_WriteByte(uint8_t data)
{
    while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
    SPI_SendData8(SPI2, data);
}

uint8_t SPI2_ReadByte(void)
{
    while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);
    return SPI_ReceiveData8(SPI2);
}
uint8_t SPI2_Transfer(uint8_t data)
{
    while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
    SPI_SendData8(SPI2, data);
    while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);
    return SPI_ReceiveData8(SPI2);
}

使用特权

评论回复
板凳
舒伯特玫瑰|  楼主 | 2022-12-31 19:24 | 只看该作者
字库驱动代码
/****送指令到晶联讯字库IC***/
void send_command_to_ROM( u16 datu )
{
#ifdef LCD_USE_HW_SPI
        //SPI2_WriteByte(datu);
        SPI2_Transfer(datu);
#else
        u16 i;
        for(i=0;i<8;i++ )
        {
                if(datu&0x80)
                        ROM_MOSI_Set();
                else
                        ROM_MOSI_Clr();
                        datu = datu<<1;
                        ROM_CLK_Clr();
                        ROM_CLK_Set();
        }
#endif
}

/****从晶联讯字库IC中取汉字或字符数据(1个字节)***/
static u8 get_data_from_ROM(void)
{
#ifdef LCD_USE_HW_SPI
        return SPI2_Transfer(0x00);
        //return        SPI2_ReadByte();
#else
        u16 i;
        u16 ret_data=0;
        ROM_CLK_Set();
        for(i=0;i<8;i++)
        {
                ROM_MISO_Set();
                ROM_CLK_Clr();
                ret_data=ret_data<<1;
                if( ROM_MISO_Get())
                        ret_data=ret_data+1;
                else
                        ret_data=ret_data+0;
                ROM_CLK_Set();
        }
        return(ret_data);
#endif
}

使用特权

评论回复
地板
舒伯特玫瑰|  楼主 | 2022-12-31 19:25 | 只看该作者
字库通信代码
void get_and_write_32x32(u32 fontaddr,u16 x,u16 y,u16 font_color,u16 back_color)
{
        u16 i,j,disp_data;
        ROM_CS_Clr();
        send_command_to_ROM(0x03);
        send_command_to_ROM((fontaddr&0xff0000)>>16);         //地址的高8位,共24位
        send_command_to_ROM((fontaddr&0xff00)>>8);                 //地址的中8位,共24位
        send_command_to_ROM(fontaddr&0xff);                                 //地址的低8位,共24位

        for(j=0;j<32;j++)
        {
                lcd_address(y,x+j,32,32);       
                for(i=0;i<4;i++)
            {
                        disp_data=get_data_from_ROM();
                        mono_data_out(disp_data,font_color,back_color);        //这一句相当于写了一行8个像素点的数据。
                }
        }
        ROM_CS_Set();
}

使用特权

评论回复
5
舒伯特玫瑰|  楼主 | 2022-12-31 19:26 | 只看该作者
主要问题点:

可以从上面的代码看到,在通信的过程中,会先发送三个字节的地址,接着就一直读取数据。

使用特权

评论回复
6
舒伯特玫瑰|  楼主 | 2022-12-31 19:28 | 只看该作者
如果字库的读取驱动按照我屏蔽的方式去通信,由于SPI是全双工通信,那么在发送完三个字节的地址数据之后,接着一直调用读取的接口,此时只会读取到一个数据,接着就读取不到数据,则一直会进入到等待数据的死循环中while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET),主要原因是因为调用SPI_ReceiveData8(SPI2)是直接从寄存器中获取数据,此时是不产生时钟信号的,这点就是我一直误解的点,因此想要产生时钟数据则需要每次在读取前发送个0x00数据才能够有时钟信号,进行全双工通信正常获取到数据。

使用特权

评论回复
7
Bowclad| | 2023-1-1 16:27 | 只看该作者
每次读取都需要先写入吗?

使用特权

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

本版积分规则

51

主题

264

帖子

2

粉丝