这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » 【换取逻辑分析仪】-硬件SPI驱动OLED屏幕

共2条 1/1 1 跳转至

【换取逻辑分析仪】-硬件SPI驱动OLED屏幕

菜鸟
2024-12-04 15:34:23   被打赏 36 分(兑奖)     打赏

本次分享的是在恩智浦LPC824芯片上通过硬件SPI来驱动OLED屏幕,结合SysTick最终设计了一个满1小时提醒的功能。

LPC82x家族所有型号都提供了SPI接口,且包含2个SPI控制器。

• SPI功能可以通过开关矩阵(switch matrix)来配置安排到所有数字引脚。

− 建议:引脚PIO0_10和PIO0_11 (open-drain pins)不要用于SPI

• 片上ROM提供SPI驱动,即有片上ROM SPI的驱动API可供调用。

1-16位的数据帧被直接支持,更大的数据帧可结合软件来实现。

• 主/从模式。

• 支持发送数据到从设备时,无需读取进来的数据。这可用于外

接SPI存储器时。

• 可以选择将控制信息随着数据一起写入。这将允许实现多种功能的操作,包括任意长度的数据帧的操作。

• 最多4条片选输入输出信号,且极性可选,使用灵活。

• 收发支持DMA。

• 支持低功耗模式(sleep/deep sleep/power down mode)唤醒。

• 注意:不支持TI的SSI和National的Microwire模式

硬件SPI框图:

image.png

根据底板与屏幕的连接,初始化用于硬件SPI功能的相关引脚:

image.png

void OLED_SPI0_Init(void)
{	
	/* SPI initialization */
	Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_SWM);
	
	Chip_SWM_MovablePinAssign(SWM_SPI0_SCK_IO,   24);
	Chip_SWM_MovablePinAssign(SWM_SPI0_MOSI_IO,  15);
	Chip_SWM_MovablePinAssign(SWM_SPI0_MISO_IO,  25);
	Chip_SWM_MovablePinAssign(SWM_SPI0_SSEL0_IO, 18);
	
	Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_SWM);
	Chip_SPI_Init(LPC_SPI0);
	
	LPC_SPI0->DIV = 30 - 1;                      /*配置SPI0的时钟频率为30M/300 = 100k*/
  LPC_SPI0->DLY = 	(0 << 0) |                                          
                    (0 << 4) |                                          
                    (0 << 8) |                                          
                    (0 << 12);                                          
	
	Chip_SPI_ConfigureSPI(LPC_SPI0, SPI_CFG_SPI_EN|  SPI_MODE_MASTER |	/* Enable master */
						  SPI_CLOCK_MODE0 |	/* Set Clock polarity to 1 */
						  SPI_CFG_MSB_FIRST_EN |/* Enable MSB first option */
							0 << 7 |
						  0<<10);	/* Chipselect is active low SSEL2 is active Low */
	LPC_SPI0->TXCTRL = (0 << 18) |                                   
                    (1 << 20) |                                      
                    (1 << 21) |                                      
                    (1 << 22) |                                      
                    ((8-1) << 24);                                   
}

非常关键的OLED写数据:

void OLED_WR_Byte(u8 dat,u8 mode){
	uint16_t tempDat;
	
	if(mode)
	  OLED_DC_Set();	// mode = 1 for Data
	else 
	  OLED_DC_Clr();	// mode = 0 for Command.	  
	OLED_CS_Clr();

	tempDat = dat;
	SPI_DATA_SETUP_T xfer = {0};
	xfer.pTx = &tempDat;	//发送数据地址
	xfer.pRx = 0;					//接收数据地址
	xfer.DataSize = 8;		//每个Frame数据大小
	xfer.Length = 1;			//有多少Frame
	Chip_SPI_WriteFrames_Blocking(LPC_SPI0, &xfer);
	
	OLED_CS_Set();
	OLED_DC_Set();
}//end of OLED_WR_Byte_HwSPI

完成上述OLED写功能后,可以调用下面的代码初始化屏幕:

//OLED的初始化
void OLED_Init(void)
{
#if BoolHwSPI
	OLED_PIN_Init_HwSPI();
#else
    OLED_PIN_Init_SwSPI();
#endif
	OLED_RES_Clr();
	delay_ms(200);
	OLED_RES_Set();
	
	OLED_WR_Byte(0xAE,OLED_CMD);//--turn off oled panel
	OLED_WR_Byte(0x00,OLED_CMD);//---set low column address
	OLED_WR_Byte(0x10,OLED_CMD);//---set high column address
	OLED_WR_Byte(0x40,OLED_CMD);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
	OLED_WR_Byte(0x81,OLED_CMD);//--set contrast control register
	OLED_WR_Byte(0x0F,OLED_CMD);// Set SEG Output Current Brightness ,原来是0xCF,我改成了0x0F
	OLED_WR_Byte(0xA1,OLED_CMD);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
	OLED_WR_Byte(0xC8,OLED_CMD);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
	OLED_WR_Byte(0xA6,OLED_CMD);//--set normal display
	OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
	OLED_WR_Byte(0x3f,OLED_CMD);//--1/64 duty
	OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset	Shift Mapping RAM Counter (0x00~0x3F)
	OLED_WR_Byte(0x00,OLED_CMD);//-not offset
	OLED_WR_Byte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency
	OLED_WR_Byte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
	OLED_WR_Byte(0xD9,OLED_CMD);//--set pre-charge period
	OLED_WR_Byte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
	OLED_WR_Byte(0xDA,OLED_CMD);//--set com pins hardware configuration
	OLED_WR_Byte(0x12,OLED_CMD);
	OLED_WR_Byte(0xDB,OLED_CMD);//--set vcomh
	OLED_WR_Byte(0x40,OLED_CMD);//Set VCOM Deselect Level
	OLED_WR_Byte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)
	OLED_WR_Byte(0x02,OLED_CMD);//
	OLED_WR_Byte(0x8D,OLED_CMD);//--set Charge Pump enable/disable
	OLED_WR_Byte(0x14,OLED_CMD);//--set(0x10) disable
	OLED_WR_Byte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)
	OLED_WR_Byte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7) 
	OLED_Clear();
	OLED_WR_Byte(0xAF,OLED_CMD);
}

在SysTick ISR中,检测按键状态:

/**
 * @brief	Handle interrupt from SysTicKtimer
 * @return	Nothing
 */
void SysTick_Handler(void)
{
	static uint32_t count;
	if(BeginTime && ((count++)%TICKRATE_HZ == 0)){
			testVal++;
	}

	
	if(keySetFlag[4]){
			keySetFlag[4] = 0;
			testVal = 0;
			OLED_ShowString(104, 24, "K4", 12, 0);
			Chip_GPIO_PinSetState(LPC_GPIO_PORT, 0, 28, 0);
			delay_ms(300);	
			Chip_GPIO_PinSetState(LPC_GPIO_PORT, 0, 28, 1);
		
			//OLED_Refresh();
	}         
}//END OF SYSTICK_HANDLER FUNCTION

在主循环中,判断是否过了1h:

	while(1){
		OLED_ShowString(48, 40, testValString,12,0);
		OLED_Refresh();
		delay_ms(100);
		if(testVal/3600 >=1){
				Chip_GPIO_PinSetState(LPC_GPIO_PORT, 0, 28, 0);
		}
	}

image.png


助工
2024-12-05 10:51:15     打赏
2楼


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]