打印
[STM32H5]

【NUCLEO- H563ZI 测评】3.SPI+OLED

[复制链接]
499|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 穿西装的强子 于 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);
  }
}


最后显示效果

使用特权

评论回复
沙发
Undshing| | 2023-8-18 10:59 | 只看该作者
freeRTOS是需要自己移植吗?

使用特权

评论回复
板凳
中国龙芯CDX| | 2023-8-21 10:14 | 只看该作者
SPI软件配置还是挺方便的,整体刷新速率快

使用特权

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

本版积分规则

10

主题

64

帖子

2

粉丝