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

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

前言

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

基本信息

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

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);
}

字库驱动代码

/****送指令到晶联讯字库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
}

字库通信代码

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();
}

主要问题点:

  1. 可以从上面的代码看到,在通信的过程中,会先发送三个字节的地址,接着就一直读取数据。
  2. 如果字库的读取驱动按照我屏蔽的方式去通信,由于SPI是全双工通信,那么在发送完三个字节的地址数据之后,接着一直调用读取的接口,此时只会读取到一个数据,接着就读取不到数据,则一直会进入到等待数据的死循环中while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET),主要原因是因为调用SPI_ReceiveData8(SPI2)是直接从寄存器中获取数据,此时是不产生时钟信号的,这点就是我一直误解的点,因此想要产生时钟数据则需要每次在读取前发送个0x00数据才能够有时钟信号,进行全双工通信正常获取到数据。
  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值