STM32基于MX的CH455硬件IIC驱动

ch455官方提供的示例代码是51单片机的io模拟iic,地址如下:

CH4XXEVT.ZIP - 南京沁恒微电子股份有限公司

但是处于效率原因,还是希望使用单片机本身的硬件IIC来与ch455通信。

首先我们先了解ch455时序

STM32CubeMX部分配置

下面是ch455的驱动,这里我使用的是三位数码管,所以代码主要数据是三位数码管的代码。

Core\Inc\ch455.h

复制代码
/**
 ******************************************************************************
 * @file           : ch455.h
 * @brief          : Header for ch455.c file.
 *                   CH455 Seven-Segment Display Driver
 ******************************************************************************
 */

#ifndef __CH455_H
#define __CH455_H

#ifdef __cplusplus
extern "C" {
#endif

/* Includes */
#include "main.h"

// 设置系统参数命令
#define CH455_BIT_ENABLE 0x01   // 开启/关闭位
#define CH455_BIT_SLEEP 0x04    // 睡眠控制位
#define CH455_BIT_7SEG 0x08     // 7段控制位
#define CH455_BIT_INTENS1 0x10  // 1级亮度
#define CH455_BIT_INTENS2 0x20  // 2级亮度
#define CH455_BIT_INTENS3 0x30  // 3级亮度
#define CH455_BIT_INTENS4 0x40  // 4级亮度
#define CH455_BIT_INTENS5 0x50  // 5级亮度
#define CH455_BIT_INTENS6 0x60  // 6级亮度
#define CH455_BIT_INTENS7 0x70  // 7级亮度
#define CH455_BIT_INTENS8 0x00  // 8级亮度
#define CH455_BIT_KOFF 0x80     // 关闭键盘

#define CH455_SYSCMD 0x4800  // 操作命令,需另加8位数据

// 加载字数据命令
#define CH455_DIG0 0x6800  // 数码管位0显示,需另加8位数据
#define CH455_DIG1 0x6A00  // 数码管位1显示,需另加8位数据
#define CH455_DIG2 0x6C00  // 数码管位2显示,需另加8位数据
#define CH455_DIG3 0x6E00  // 数码管位3显示,需另加8位数据

#define BCD_decode_DP 0x0080
#define BCD_decode_NG 0x0040

/* Seven-Segment Display Character Macros */
#define CH455_CHAR_0 0x00
#define CH455_CHAR_1 0x01
#define CH455_CHAR_2 0x02
#define CH455_CHAR_3 0x03
#define CH455_CHAR_4 0x04
#define CH455_CHAR_5 0x05
#define CH455_CHAR_6 0x06
#define CH455_CHAR_7 0x07
#define CH455_CHAR_8 0x08
#define CH455_CHAR_9 0x09
#define CH455_CHAR_A 0x0A
#define CH455_CHAR_B 0x0B
#define CH455_CHAR_C 0x0C
#define CH455_CHAR_D 0x0D
#define CH455_CHAR_E 0x0E
#define CH455_CHAR_F 0x0F
#define CH455_CHAR_G 0x10
#define CH455_CHAR_H 0x11
#define CH455_CHAR_I 0x12
#define CH455_CHAR_J 0x13
#define CH455_CHAR_K 0x14
#define CH455_CHAR_L 0x15
#define CH455_CHAR_M 0x16
#define CH455_CHAR_N 0x17
#define CH455_CHAR_O 0x18
#define CH455_CHAR_P 0x19
#define CH455_CHAR_Q 0x1A
#define CH455_CHAR_R 0x1B
#define CH455_CHAR_S 0x1C
#define CH455_CHAR_T 0x1D
#define CH455_CHAR_U 0x1E
#define CH455_CHAR_V 0x1F
#define CH455_CHAR_W 0x20
#define CH455_CHAR_X 0x21
#define CH455_CHAR_Y 0x22
#define CH455_CHAR_Z 0x23
#define CH455_CHAR_SPACE 0x24
#define CH455_CHAR_DASH 0x25

/* Exported functions prototypes */
void CH455G_Init(uint8_t intens);
void CH455G_SetDigit(uint8_t position, uint8_t value);
void CH455G_SetDigits(uint8_t d0, uint8_t d1, uint8_t d2);
void CH455G_SetNumber(uint16_t number);
void CH455G_SetAllSegments(void);
void CH455G_SetRaw(uint8_t position, uint8_t data);

#ifdef __cplusplus
}
#endif

#endif /* __CH455_H */

Core\Src\ch455.c

复制代码
/**
 ******************************************************************************
 * @file           : ch455.c
 * @brief          : CH455 Seven-Segment Display Driver
 *                   Common Cathode 3-Digit Display
 *                   DIG0=Left, DIG1=Middle, DIG2=Right
 *                   SEG0=A, SEG1=B, SEG2=C, SEG3=D, SEG4=E, SEG5=F, SEG6=DP
 ******************************************************************************
 */

#include "ch455.h"

#include "main.h"
#include "i2c.h"

/* Common Cathode 7-Segment Display Code Table */
/* Segments: A=SEG0, B=SEG1, C=SEG2, D=SEG3, E=SEG4, F=SEG5, G=SEG6, DP=SEG7 */
static const uint8_t ch455_seg_code[] = {
    0x3F, /* 0: A+B+C+D+E+F */
    0x06, /* 1: B+C */
    0x5B, /* 2: A+B+G+E+D */
    0x4F, /* 3: A+B+G+C+D */
    0x66, /* 4: F+G+B+C */
    0x6D, /* 5: A+F+G+C+D */
    0x7D, /* 6: A+F+G+C+D+E */
    0x07, /* 7: A+B+C */
    0x7F, /* 8: All segments (A-G) */
    0x6F, /* 9: A+B+C+D+F+G */
    0x77, /* A: A+B+C+E+F+G */
    0x7C, /* b: F+G+C+D+E */
    0x39, /* C: A+D+E+F */
    0x5E, /* d: B+C+D+E+G */
    0x79, /* E: A+D+E+F+G */
    0x71, /* F: A+E+F+G */
    0x3D, /* G: A+B+C+D+E+F */
    0x76, /* H: B+C+E+F+G */
    0x06, /* I: B+C (same as 1) */
    0x1F, /* J: A+B+C+D+G */
    0x76, /* K: Same as H */
    0x38, /* L: A+D+E+F */
    0x55, /* M: A+B+C+E+G (double-height) */
    0x74, /* N: A+B+C+E+F+G */
    0x3F, /* O: A+B+C+D+E+F (same as 0) */
    0x73, /* P: A+B+C+E+F+G */
    0x67, /* Q: A+B+C+D+F+G */
    0x50, /* R: A+E+F+G */
    0x6D, /* S: Same as 5 */
    0x78, /* T: E+F+G */
    0x3E, /* U: A+B+C+D+E */
    0x1C, /* V: A+B+C+D+E (slant) */
    0x3E, /* W: Same as U */
    0x6E, /* X: Same as H */
    0x6F, /* Y: A+B+C+D+F+G (same as 9) */
    0x5B, /* Z: Same as 2 */
    0x00, /* Space */
    0x40, /* - (Dash) */
};

/**
 * @brief  Write command to CH455
 * @param  cmd: Command byte
 * @retval HAL status
 */
static HAL_StatusTypeDef CH455G_Write(uint16_t cmd)
{
    uint8_t data1 = 0;
    uint8_t data2 = 0;
    data1 = (uint8_t)(cmd >> 8);
    data2 = (uint8_t)(cmd & 0x00ff);
    return HAL_I2C_Master_Transmit(&hi2c1, data1, &data2, 1, 1000);
    // __NOP();
}

/**
 * @brief  Initialize CH455
 * @param  intens: CH455_BIT_INTENS1-8
 * @retval None
 */
void CH455G_Init(uint8_t intens)
{
    if ((intens != CH455_BIT_INTENS1) && (intens != CH455_BIT_INTENS2) && (intens != CH455_BIT_INTENS3) &&
        (intens != CH455_BIT_INTENS4) && (intens != CH455_BIT_INTENS5) && (intens != CH455_BIT_INTENS6) &&
        (intens != CH455_BIT_INTENS7) && (intens != CH455_BIT_INTENS8)) {
        CH455G_Write(CH455_SYSCMD | CH455_BIT_ENABLE | CH455_BIT_INTENS4);
    } else {
        CH455G_Write(CH455_SYSCMD | CH455_BIT_ENABLE | intens);
    }
    /* Clear all digits */
    CH455G_SetDigits(CH455_CHAR_SPACE, CH455_CHAR_SPACE, CH455_CHAR_SPACE);
}

/**
 * @brief  Set a single digit
 * @param  position: 0=Left, 1=Middle, 2=Right
 * @param  value: 0-15=0-F, 16=Space, 17=Dash
 * @retval None
 */
void CH455G_SetDigit(uint8_t position, uint8_t value)
{
    if (position > 2) return;
    if (value > sizeof(ch455_seg_code) - 1) value = CH455_CHAR_SPACE; /* Default to space */

    switch (position)
    {
    case 0:
        /* Leftmost digit */
        CH455G_Write(CH455_DIG0 | ch455_seg_code[value]);
        break;
    case 1:
        /* Middle digit */
        CH455G_Write(CH455_DIG1 | ch455_seg_code[value]);
        break;
    case 2:
        /* Rightmost digit */
        CH455G_Write(CH455_DIG2 | ch455_seg_code[value]);
        break;  
    default:
        break;
    }
}

/**
 * @brief  Set all three digits at once
 * @param  d0: Left digit (0-17)
 * @param  d1: Middle digit (0-17)
 * @param  d2: Right digit (0-17)
 * @retval None
 */
void CH455G_SetDigits(uint8_t d0, uint8_t d1, uint8_t d2)
{
    CH455G_SetDigit(0, d0);
    CH455G_SetDigit(1, d1);
    CH455G_SetDigit(2, d2);
}

/**
 * @brief  Display a number (0-999)
 * @param  number: Number to display (0-999)
 * @retval None
 */
void CH455G_SetNumber(uint16_t number)
{
    if (number > 999) number = 999;

    uint8_t d0 = (number / 100) % 10; /* Hundreds */
    uint8_t d1 = (number / 10) % 10;  /* Tens */
    uint8_t d2 = number % 10;         /* Ones */

    CH455G_SetDigits(d0, d1, d2);
}

/**
 * @brief  Turn on all segments of all digits (test mode)
 * @param  None
 * @retval None
 */
void CH455G_SetAllSegments(void)
{
    /* 0x7F = All segments + decimal point */
    CH455G_Write(CH455_DIG0 | 0xFF);
    CH455G_Write(CH455_DIG1 | 0xFF);
    CH455G_Write(CH455_DIG2 | 0xFF);
}

/**
 * @brief  Set raw segment data directly
 * @param  position: 0=Left, 1=Middle, 2=Right
 * @param  data: 8-bit raw segment data (bit7=DP, bit6=G, bit5=F, bit4=E, bit3=D, bit2=C, bit1=B, bit0=A)
 * @retval None
 */
void CH455G_SetRaw(uint8_t position, uint8_t data)
{
    if (position > 2) return;

    switch (position)
    {
    case 0:
        CH455G_Write(CH455_DIG0 | data);
        break;
    case 1:
        CH455G_Write(CH455_DIG1 | data);
        break;
    case 2:
        CH455G_Write(CH455_DIG2 | data);
        break;
    default:
        break;
    }
}

使用方法距离如下

复制代码
CH455G_SetRaw(0, 0x20);
CH455G_SetNumber(123);
CH455G_SetDigits(CH455_CHAR_SPACE, CH455_CHAR_SPACE, CH455_CHAR_SPACE);

这个ch455并不是标准的iic器件,所以没有iic地址,使用的是命令码+数据的方式通信。