本次分享的是在恩智浦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框图:

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

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);
}
}
我要赚赏金
