Tutorial STM32CubeMx (6) - Uso de la pantalla OLED

prefacio

En el capítulo anterior, aprendí sobre la comunicación en serie y los temporizadores. En este capítulo, se presentará la comunicación I2C y el módulo OLED se iluminará mediante la comunicación I2C. Dado que el módulo OLED admite múltiples métodos de comunicación, el proceso de comunicación I2C del módulo OLED utiliza principalmente paquetes secundarios en la capa de datos para lograr el propósito de clasificar los paquetes de datos para adaptarse a varios métodos de comunicación del OLED.

herramientas de preparación

Software: STM32CubeMx, Keil5 MDK

Hardware: placa central STM32F103C8T6, descargador ST_LINK, pantalla de 4 pines de comunicación OLEDI2C

El proyecto de este capítulo se ha subido a Baidu Netdisk y este enlace es válido de forma permanente.

Enlace: https://pan.baidu.com/s/13UiC3hnn84yIsA5N1nrmmg?pwd=w8cx 
Código de extracción: w8cx

comunicación I2C

I2C es un bus serial síncrono de dos hilos, de dos vías y semidúplex desarrollado por PHILIPS. El sistema de dos cables significa que I2C solo necesita dos líneas de señal, una línea de datos SDA y la otra es la línea de reloj SCL. El bus I2C permite montar varios dispositivos maestros, pero el reloj del bus solo puede ser generado por un dispositivo maestro a la vez, y cada dispositivo conectado al bus debe tener una dirección I2C única, y el dispositivo esclavo puede ser direccionado. por el dispositivo maestro. La comunicación I2C tiene varias clases de señales:

Señal de inicio S: cuando SCL está en un nivel alto, SDA pasa de un nivel alto a un nivel bajo, lo que representa el inicio de la transmisión de datos.

Señal final P: cuando SCL está en un nivel alto, SDA pasa de un nivel bajo a un nivel alto, lo que representa el final de la transmisión de datos.

Señal de datos: la señal de datos transmite 8 bits de datos cada vez, y cada bit de datos se transmite dentro de un ciclo de reloj. Cuando SCL está en un nivel alto, el nivel de la línea de datos SDA debe ser estable. Cuando SCL está en un nivel bajo nivel, en este momento, el nivel en la línea de datos SDA puede cambiar.

Señal de respuesta ACK/NACK: La señal de respuesta es que el maestro envía datos de 8 bits y el esclavo envía un nivel bajo al maestro, lo que indica que los datos han sido aceptados.
El proceso de transmisión I2C común para leer los datos del sensor se muestra en la siguiente tabla:

Todo el proceso de comunicación I2C se entiende como el proceso de envío y recepción de entrega urgente. La dirección I2C del dispositivo se entiende como la dirección del gabinete expreso de la escuela. Los dígitos de lectura y escritura representan el envío y la firma para entrega urgente. Firmado para mensajería . Todo el proceso es como ir al gabinete de mensajería de la escuela (dirección I2C esclava), enviar o firmar por el servicio de mensajería (datos) para el número de gabinete (dirección de registro). 

Configuración de IIC en CubeMx

1. Busque I2C1 en conectividad,
2. Configure como I2C,
3. Configure como modo rápido,
4. Otros permanecen predeterminados.

 

Genere código y abra el proyecto.

Agregue el siguiente código al proyecto

/**
  * @brief          写数据或者指令到OLED, 如果使用的是SPI,请重写这个函数
  * @param[in]      dat: 要写入的字节
  * @param[in]      cmd: OLED_CMD 代表写入的字节是指令; OLED_DATA 代表写入的字节是数据
  * @retval         none
  */
void oled_write_byte(uint8_t dat, uint8_t cmd)
{
    static uint8_t cmd_data[2];
    if(cmd == OLED_CMD)
    {
        cmd_data[0] = 0x00;
    }
    else
    {
        cmd_data[0] = 0x40;
    }
    cmd_data[1] = dat;
    HAL_I2C_Master_Transmit(&hi2c1, OLED_I2C_ADDRESS, cmd_data, 2, 10);
}

Según el método de comunicación de OLED, es necesario indicar el tipo de datos en el primer byte, si es un comando de control, debe enviar 0x00, y si es un comando de datos, debe enviar 0x40.

/**
  * @brief          初始化OLED模块,
  * @param[in]      none
  * @retval         none
  */
void OLED_init(void)
{
    oled_write_byte(0xAE, OLED_CMD);    //display off
    oled_write_byte(0x20, OLED_CMD);    //Set Memory Addressing Mode	
    oled_write_byte(0x10, OLED_CMD);    //00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid
    oled_write_byte(0xb0, OLED_CMD);    //Set Page Start Address for Page Addressing Mode,0-7
    oled_write_byte(0xc8, OLED_CMD);    //Set COM Output Scan Direction
    oled_write_byte(0x00, OLED_CMD);    //---set low column address
    oled_write_byte(0x10, OLED_CMD);    //---set high column address
    oled_write_byte(0x40, OLED_CMD);    //--set start line address
    oled_write_byte(0x81, OLED_CMD);    //--set contrast control register
    oled_write_byte(0xff, OLED_CMD);    //brightness 0x00~0xff
    oled_write_byte(0xa1, OLED_CMD);    //--set segment re-map 0 to 127
    oled_write_byte(0xa6, OLED_CMD);    //--set normal display
    oled_write_byte(0xa8, OLED_CMD);    //--set multiplex ratio(1 to 64)
    oled_write_byte(0x3F, OLED_CMD);    //
    oled_write_byte(0xa4, OLED_CMD);    //0xa4,Output follows RAM content;0xa5,Output ignores RAM content
    oled_write_byte(0xd3, OLED_CMD);    //-set display offset
    oled_write_byte(0x00, OLED_CMD);    //-not offset
    oled_write_byte(0xd5, OLED_CMD);    //--set display clock divide ratio/oscillator frequency
    oled_write_byte(0xf0, OLED_CMD);    //--set divide ratio
    oled_write_byte(0xd9, OLED_CMD);    //--set pre-charge period
    oled_write_byte(0x22, OLED_CMD);    //
    oled_write_byte(0xda, OLED_CMD);    //--set com pins hardware configuration
    oled_write_byte(0x12, OLED_CMD);
    oled_write_byte(0xdb, OLED_CMD);    //--set vcomh
    oled_write_byte(0x20, OLED_CMD);    //0x20,0.77xVcc
    oled_write_byte(0x8d, OLED_CMD);    //--set DC-DC enable
    oled_write_byte(0x14, OLED_CMD);    //
    oled_write_byte(0xaf, OLED_CMD);    //--turn on oled panel
}

La función OLED_init, que configura principalmente los parámetros OLED, pasa OLED_CMD llamando a oled_write_byte y transmite comandos de control para completar la configuración.

/**
  * @brief          操作GRAM内存(128*8char数组)
  * @param[in]      pen: 操作类型.
                    PEN_CLEAR: 设置为0x00
                    PEN_WRITE: 设置为0xff
                    PEN_INVERSION: 按位取反
  * @retval         none
  */
void OLED_operate_gram(pen_typedef pen)
{
    uint8_t i, n;

    for (i = 0; i < 8; i++)
    {
        for (n = 0; n < 128; n++)
        {
            if (pen == PEN_WRITE)
            {
                OLED_GRAM[n][i] = 0xff;
            }
            else if (pen == PEN_CLEAR)
            {
                OLED_GRAM[n][i] = 0x00;
            }
            else
            {
                OLED_GRAM[n][i] = 0xff - OLED_GRAM[n][i];
            }
        }
    }
}

/**
  * @brief          发送数据到OLED的GRAM
  * @param[in]      none
  * @retval         none
  */
void OLED_refresh_gram(void)
{
    uint8_t i, n;

    for (i = 0; i < 8; i++)
    {
        OLED_set_pos(0, i);
        for (n = 0; n < 128; n++)
        {
            oled_write_byte(OLED_GRAM[n][i], OLED_DATA);
        }
    }
}

/**
  * @brief          显示一个字符
  * @param[in]      row: 字符的开始行
  * @param[in]      col: 字符的开始列
  * @param[in]      chr: 字符
  * @retval         none
  */
void OLED_show_char(uint8_t row, uint8_t col, uint8_t chr)
{
    uint8_t x = col * 6;
    uint8_t y = row * 12;
    uint8_t temp, t, t1;
    uint8_t y0 = y;
    chr = chr - ' ';

    for (t = 0; t < 12; t++)
    {
        temp = asc2_1206[chr][t];

        for (t1 = 0; t1 < 8; t1++)
        {
            if (temp&0x80)
                OLED_draw_point(x, y, PEN_WRITE);
            else
                OLED_draw_point(x, y, PEN_CLEAR);

            temp <<= 1;
            y++;
            if ((y - y0) == 12)
            {
                y = y0;
                x++;
                break;
            }
        }
    }
}

/**
  * @brief          显示一个字符串
  * @param[in]      row: 字符串的开始行
  * @param[in]      col: 字符串的开始列
  * @param[in]      chr: 字符串
  * @retval         none
  */
void OLED_show_string(uint8_t row, uint8_t col, uint8_t *chr)
{
    uint8_t n =0;

    while (chr[n] != '\0')
    {
        OLED_show_char(row, col, chr[n]);
        col++;

        if (col > 20)
        {
            col = 0;
            row += 1;
        }
        n++;
    }
}

El proceso de visualización es el siguiente:
1. Inicialice el módulo OLED, llame a OLED_init
2. Opere la matriz GRAM en stm32 a través de la función de caracteres de visualización
3. Llame a la función OLED_refresh_gram para transferir los datos GRAM a la GRAM del módulo OLED para su visualización.
función principal

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM4_Init();
  MX_I2C1_Init();
  MX_TIM3_Init();
  /* USER CODE BEGIN 2 */
	HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_1); //初始化BUZZER
	HAL_TIM_Base_Start_IT(&htim3);	//开启定时器3中断
	OLED_init(); //OLED初始化
//	Solitary_brave();
	OLED_operate_gram(PEN_CLEAR);
	OLED_show_string(0,6,"LRJ_ROBOT");
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		if(tim3_delay.count_10ms != tim3_delay.last_count_10ms)
		{
			GPIO_PinState pin_state = HAL_GPIO_ReadPin(LEDD_GPIO_Port, LEDD_Pin);//获取LED电平
			OLED_printf(2,5,"LED_PIN = %d",pin_state);
			tim3_delay.last_count_10ms = tim3_delay.count_10ms;
		}
		if(tim3_delay.count_400ms != tim3_delay.last_count_400ms)
		{
			OLED_refresh_gram();//屏幕刷新 400ms
			HAL_GPIO_TogglePin(LEDD_GPIO_Port, LEDD_Pin);
			tim3_delay.last_count_400ms = tim3_delay.count_400ms;
		}
		
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

La pantalla OLED muestra los cambios de nivel de LED en tiempo real

Supongo que te gusta

Origin blog.csdn.net/weixin_49821504/article/details/126854875
Recomendado
Clasificación