本帖最后由 穿西装的强子 于 2023-7-22 10:27 编辑
SPI硬件接口使用SPI1,PA5-SCK,PB5-MOSI,PD14-CS,PD15-DC,PF3-REST,因为不需要读取,所以MISO不需要用。
SPI软件配置,使用了2线的只发接口,SPI_DIRECTION_2LINES_TXONLY,分频为32分频=250M/32=7.8125MHz,速度太快屏幕受不了 - -!。
static void MX_SPI1_Init(void)
{
/* USER CODE END SPI1_Init 1 */
/* SPI1 parameter configuration*/
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES_TXONLY;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 0x7;
hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
hspi1.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
hspi1.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
hspi1.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
hspi1.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
hspi1.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
hspi1.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
hspi1.Init.IOSwap = SPI_IO_SWAP_DISABLE;
hspi1.Init.ReadyMasterManagement = SPI_RDY_MASTER_MANAGEMENT_INTERNALLY;
hspi1.Init.ReadyPolarity = SPI_RDY_POLARITY_HIGH;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI1_Init 2 */
/* USER CODE END SPI1_Init 2 */
}/**
* [url=home.php?mod=space&uid=247401]@brief[/url] SPI MSP Initialization
* This function configures the hardware resources used in this example
* @param hspi: SPI handle pointer
* @retval None
*/
void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
if(hspi->Instance==SPI1)
{
/* USER CODE BEGIN SPI1_MspInit 0 */
/* USER CODE END SPI1_MspInit 0 */
/** Initializes the peripherals clock
*/
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI1;
PeriphClkInitStruct.Spi1ClockSelection = RCC_SPI1CLKSOURCE_PLL1Q;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
/* Peripheral clock enable */
__HAL_RCC_SPI1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**SPI1 GPIO Configuration
PA5 ------> SPI1_SCK
PA6 ------> SPI1_MISO
PB5 ------> SPI1_MOSI
*/
GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* SPI1 interrupt Init */
HAL_NVIC_SetPriority(SPI1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(SPI1_IRQn);
/* USER CODE BEGIN SPI1_MspInit 1 */
/* USER CODE END SPI1_MspInit 1 */
}
}
SPI发送函数处理,发送后等待发送标值结束,并且增加超时功能,若5000次循环都没有完成,则结束本次等待。
void SPI1_SEND(uint8_t *data,uint8_t len)
{
int32_t cnt;
uint8_t rx[2] = {1};
HAL_SPI_TransmitReceive_IT(&hspi1, data, rx, len);
cnt = 5000;
while (wTransferState == TRANSFER_WAIT && cnt-->0);
wTransferState = TRANSFER_WAIT;
}
OLED的GPIO初始化
void DevOLED_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOF_CLK_ENABLE();
// /*Configure GPIO pin Output Level */
// HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET);
// /*Configure GPIO pin Output Level */
// HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_RESET);
// /*Configure GPIO pin Output Level */
// HAL_GPIO_WritePin(GPIOF, GPIO_PIN_3, GPIO_PIN_RESET);
GPIO_InitStruct.Pin = GPIO_PIN_14;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/*Configure GPIO pin : LED3_Pin */
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
}
OLED配置,其它的如何移植就不在赘述了,都很简单,
void DevOLED_Init(void)
{
DevOLED_GPIO_Init();
//SPI
RST_H; //SPI RST
HAL_Delay(100);
RST_L;
HAL_Delay(100);
RST_H;
HAL_Delay(100);
DevOLED_WRByte(0xAE,OLED_CMD);//--turn off oled panel
DevOLED_WRByte(0x00,OLED_CMD);//---set low column address
DevOLED_WRByte(0x10,OLED_CMD);//---set high column address
DevOLED_WRByte(0x40,OLED_CMD);//--set start line address Set Mapping RAM Display Start Line (0x00~0x3F)
DevOLED_WRByte(0x81,OLED_CMD);//--set contrast control register
DevOLED_WRByte(0xCF,OLED_CMD); // Set SEG Output Current Brightness
DevOLED_WRByte(0xA1,OLED_CMD);//--Set SEG/Column Mapping 0xa0×óÓÒ·´ÖÃ 0xa1Õý³£
DevOLED_WRByte(0xC8,OLED_CMD);//Set COM/Row Scan Direction 0xc0ÉÏÏ·´Öà 0xc8Õý³£
DevOLED_WRByte(0xA6,OLED_CMD);//--set normal display
DevOLED_WRByte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
DevOLED_WRByte(0x3f,OLED_CMD);//--1/64 duty
DevOLED_WRByte(0xD3,OLED_CMD);//-set display offset Shift Mapping RAM Counter (0x00~0x3F)
DevOLED_WRByte(0x00,OLED_CMD);//-not offset
DevOLED_WRByte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency
DevOLED_WRByte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
DevOLED_WRByte(0xD9,OLED_CMD);//--set pre-charge period
DevOLED_WRByte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
DevOLED_WRByte(0xDA,OLED_CMD);//--set com pins hardware configuration
DevOLED_WRByte(0x12,OLED_CMD);
DevOLED_WRByte(0xDB,OLED_CMD);//--set vcomh
DevOLED_WRByte(0x40,OLED_CMD);//Set VCOM Deselect Level
DevOLED_WRByte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)
DevOLED_WRByte(0x02,OLED_CMD);//
DevOLED_WRByte(0x8D,OLED_CMD);//--set Charge Pump enable/disable
DevOLED_WRByte(0x14,OLED_CMD);//--set(0x10) disable
DevOLED_WRByte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)
DevOLED_WRByte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7)
DevOLED_WRByte(0xAF,OLED_CMD);//--turn on oled panel
DevOLED_WRByte(0xAF,OLED_CMD); /*display ON*/
DevOLED_Clear();
DevOLED_Set_Pos(0,0);
DevOLED_UIInit();
}
void DevOLED_UIInit(void)
{
//固定显示第一行,不刷新,显示中文“时间”和“:”
DevOLED_ShowChinese(0,0,0,16);
DevOLED_ShowChinese(1,0,1,16);
DevOLED_ShowString(2,0,":",16);
}
FreeRTOS任务刷新显示,system_count是1ms定时器累计数值。
void DevOLED_UIHandle(void)
{
DevOLED_ShowTime(44,0,system_count/1000,16);
}
void LEDThread_Entry(void *argument)
{
(void) argument;
printf("system start\r\n");
while(1)
{
DevOLED_UIHandle();
HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
/* Delay for 500ms */
vTaskDelay(50);
HAL_GPIO_TogglePin(LED2_GPIO_Port, LED2_Pin);
vTaskDelay(50);
HAL_GPIO_TogglePin(LED3_GPIO_Port, LED3_Pin);
vTaskDelay(50);
}
}
最后显示效果
|