资讯详情

STM32F1与STM32CubeIDE编程实例-TM1637驱动4位7段数码管

TM1637驱动4段数字管

1、TM1637介绍

TM1637 带键盘扫描接口的一种LED(发光二极管显示器) 驱动控制专用电路, 内部集成有MCU 数字接口,数据存器,LED 高压驱动、键盘扫描等电路。本产品性能优良,质量可靠。主要用于电磁炉、微波炉和小家电的显示驱动。

在这里插入图片描述

在前面的文章中,是的TM详细描述了1637的驱动,请参考:

  • ESP32-IDF传感器模块编程实例-TM1637数码管
  • Arduino与Proteus仿真实例-TM1637驱动4位7段数字仿真

2、TM1637配置

请参考开发环境建设、系统时钟配置、调试配置和串口配置:

  • STM32F1与STM32CubeIDE快速入门-开发环境建设
  • STM32F1与STM32CubeIDE快速入门-GPIO概述与点亮LED
  • STM32F1与STM32CubeIDE快速入门-USART/UART串口通信

本次实例的TM1637配置如下:

3、TM1637驱动实现

/* * tm1637_simple.h * * Created on: May 5, 2022 * Author: jenson */  #ifndef TM1637_SIMPLE_TM1637_SIMPLE_H_ #define TM1637_SIMPLE_TM1637_SIMPLE_H_  #include <stdio.h> #include <stm32f1xx_hal.h> #include <stdbool.h>  #define TM1637_ADDR_AUTO 0x40 // 自动地址 #define TM1637_ADDR_FIXED 0x44 // 固定地址  #define MINUS_SIGN_IDX 16 #define TM1637_DELAY_US 3 #define TM1637_MAX_BRIGHTNESS 0x07 #define TM_DEG 0x63  #define INDEX_NEGATIVE_SIGN 16 #define INDEX_BLANK 0 // 17 nothing ,0 zero beter for clock  typedef struct { 
          uint16_t id;  GPIO_TypeDef *CLK_GPIOx; // CLK端口 uint16_t CLK_GPIO_Pinx; // CLK引脚 GPIO_TypeDef *DIO_GPIOx; // DIO端口 uint16_t DIO_GPIO_Pinx; // DIO引脚 uint8_t brightness; // 亮度 uint8_t digital_bits; // 位数 bool dot_blink_state; } tm1637_t; /** * @brief 初始化 * @param tm1637 tm1637_t对象 */ void tm1637_init(tm1637_t *tm1637); /** * @brief 设置亮度 * @param tm1637 tm1637_t对象 * @param level uint8_t 亮度级别,最大值为7 */ void tm1637_set_brightness(tm1637_t *tm1637, uint8_t level); /** * @brief 在指定位显示数字 * @param tm1637 tm1637_t对象 * @param segment_idx uint8_t 位数,不能超过tm1637_t对象的最大位数 * @param number uint8_t 需要显示的数字(0~9) * @param dot bool 是否显示点 */ void tm1637_set_segment_number(tm1637_t *tm1637, uint8_t segment_idx, const uint8_t number, const bool dot); /** * @brief 显示带有前导0及小数点的数字 * @param tm1637 tm1637_t对象 * @param number uint16_t 所要显示的数字,数字最大位数和小点和前导0的总位数不能超过tm1637_t的最大位数。 * @param lead_zero bool 是否显示前导0 * @param dot_mask uint8_t 点掩码 */ void tm1637_set_number_lead_dot(tm1637_t *tm1637, uint16_t number, bool lead_zero, const uint8_t dot_mask); /** * @brief 显示温度 * @param tm1637 tm1637_t对象 * @param temperature uint16_t 温度值,值范围为[-99~999]之间 */ void tm1637_display_temperature(tm1637_t *tm1637, int16_t temperature); /** * @brief 显示温度 * @param tm1637 tm1637_t对象 * @param number int16_t 数字,范围[-999~9999] */ void tm1637_display_number(tm1637_t *tm1637, int16_t number); /** * @brieef 显示浮点值 * @param tm1637 tm1637_t对象 * @param value float 显示的浮点值 */ void tm1637_display_float(tm1637_t *tm1637, float value); /** * @brief 显示字符 * @param tm1637 tm1637_t对象 * @param data uint8_t* 字符 */ void tm1637_display_string(tm1637_t *tm1637, const int8_t *data); /** * @brief 显示时间 * @param tm1637 tm1637_t对象 * @param hours uint8_t 时 * @param minutes uint8_t 分 */ void tm1637_display_time(tm1637_t* tm1637,uint8_t hours,uint8_t minutes,bool dot_blink); /** * @brief 清屏 * @param tm1637 tm1637_t对象 */ void tm1637_clear(tm1637_t *tm1637); #endif /* TM1637_SIMPLE_TM1637_SIMPLE_H_ */ 

/* * 七段管定义 //Segments // --0x01-- // | | //0x20 0x02 // | | // --0x40- - // | | //0x10 0x04 // | | // --0x08-- * */

static const int8_t __tm1637_symbols[] = { 
        
// XGFEDCBA
		0x3f,// 0b00111111, // 0
		0x06, // 0b00000110, // 1
		0x5b, // 0b01011011, // 2
		0x4f, // 0b01001111, // 3
		0x66, // 0b01100110, // 4
		0x6d, // 0b01101101, // 5
		0x7d, // 0b01111101, // 6
		0x07, // 0b00000111, // 7
		0x7f, // 0b01111111, // 8
		0x6f, // 0b01101111, // 9
		0x77, // 0b01110111, // A
		0x7c, // 0b01111100, // b
		0x39, // 0b00111001, // C
		0x5e, // 0b01011110, // d
		0x79, // 0b01111001, // E
		0x71, // 0b01110001 // F
		0x40, // 0b01000000 // minus sign
		};

static const uint8_t __s_ascii[] = { 
         0x00, // 032 (Space)
		0x30, // 033 !
		0x22, // 034 "
		0x41, // 035 #
		0x6D, // 036 $
		0x52, // 037 %
		0x7C, // 038 &
		0x20, // 039 '
		0x39, // 040 (
		0x0F, // 041 )
		0x21, // 042 *
		0x70, // 043 +
		0x08, // 044 ,
		0x40, // 045 -
		0x80, // 046 .
		0x52, // 047 /
		0x3F, // 048 0
		0x06, // 049 1
		0x5B, // 050 2
		0x4F, // 051 3
		0x66, // 052 4
		0x6D, // 053 5
		0x7D, // 054 6
		0x07, // 055 7
		0x7F, // 056 8
		0x6F, // 057 9
		0x48, // 058 :
		0x48, // 059 ;
		0x39, // 060 <
		0x48, // 061 =
		0x0F, // 062 >
		0x53, // 063 ?
		0x5F, // 064 @
		0x77, // 065 A
		0x7C, // 066 B
		0x39, // 067 C
		0x5E, // 068 D
		0x79, // 069 E
		0x71, // 070 F
		0x3D, // 071 G
		0x76, // 072 H
		0x30, // 073 I
		0x1E, // 074 J
		0x7A, // 075 K
		0x38, // 076 L
		0x55, // 077 M
		0x54, // 078 N
		0x5C, // 079 O
		0x73, // 080 P
		0x67, // 081 Q
		0x50, // 082 R
		0x6D, // 083 S
		0x78, // 084 T
		0x3E, // 085 U
		0x7E, // 086 V
		0x6A, // 087 W
		0x36, // 088 X
		0x6E, // 089 Y
		0x48, // 090 Z
		0x39, // 091 [
		0x64, // 092 (backslash)
		0x0F, // 093 ]
		0x23, // 094 ^
		0x08, // 095 _
		0x20, // 096 `
		0x77, // 097 a
		0x7C, // 098 b
		0x58, // 099 c
		0x5E, // 100 d
		0x79, // 101 e
		0x71, // 102 f
		0x3D, // 103 g
		0x74, // 104 h
		0x10, // 105 i
		0x1E, // 106 j
		0x7A, // 107 k
		0x18, // 108 l
		0x55, // 109 m
		0x54, // 110 n
		0x5C, // 111 o
		0x73, // 112 p
		0x67, // 113 q
		0x50, // 114 r
		0x6D, // 115 s
		0x78, // 116 t
		0x1C, // 117 u
		0x1C, // 118 v
		0x6A, // 119 w
		0x36, // 120 x
		0x6E, // 121 y
		0x48, // 122 z
		0x39, // 123 { 
        
		0x30, // 124 |
		0x0F, // 125 }
		0x40, // 126 ~
		0x00  // 127 
		};

// CLK引脚设置高电平
void __tm1637_clk_high(tm1637_t *tm1637);
// CLK引脚设置低电平
void __tm1637_clk_low(tm1637_t *tm1637);
// DIO引脚设置高电平
void __tm1637_dio_high(tm1637_t *tm1637);
// DIO引脚设置低电平
void __tm1637_dio_low(tm1637_t *tm1637);
// 将DIO设置为输入
void __tm1637_dio_set_input(tm1637_t *tm1637);
// 将DIO设置为输出
void __tm1637_dio_set_output(tm1637_t *tm1637);
void __tm1637_delay_us(uint32_t us);
// TM1637固定延时3us
void __tm1637_delay();
// 发送开始信号
void __tm1637_start(tm1637_t *tm1637);
// 发送结束信号
void __tm1637_stop(tm1637_t *tm1637);

// 读取响应
void __tm1637_ack(tm1637_t *tm1637);

// 发送一位数据
void __tm1637_send_byte(tm1637_t *tm1637, uint8_t byte);
// 调节亮度
void __tm1637_adjust_brightness(tm1637_t *tm1637);
// 向TM1637发送数据
void __tm1637_set_segment_raw_data(tm1637_t *tm1637, const uint8_t segment_idx,
		const uint8_t data);
// 设置前导点
void __tm1637_set_lead_dot(tm1637_t *tm1637, const bool lead_zero);
// 查找ASCII表码
uint8_t __tm1637_encode(uint8_t chr);
// 查询位
uint8_t __tm1637_digit_map(tm1637_t *tm1637, uint8_t digits, uint8_t digit);

static inline float nearestf(float val, int precision) { 
        
	int scale = pow(10, precision);
	return roundf(val * scale) / scale;
}

// CLK引脚设置高电平
void __tm1637_clk_high(tm1637_t *tm1637) { 
        
	HAL_GPIO_WritePin(tm1637->CLK_GPIOx, tm1637->CLK_GPIO_Pinx, GPIO_PIN_SET);
}

// CLK引脚设置低电平
void __tm1637_clk_low(tm1637_t *tm1637) { 
        
	HAL_GPIO_WritePin(tm1637->CLK_GPIOx, tm1637->CLK_GPIO_Pinx, GPIO_PIN_RESET);
}

// DIO引脚设置高电平
void __tm1637_dio_high(tm1637_t *tm1637) { 
        
	HAL_GPIO_WritePin(tm1637->DIO_GPIOx, tm1637->DIO_GPIO_Pinx, GPIO_PIN_SET);
}

// DIO引脚设置低电平
void __tm1637_dio_low(tm1637_t *tm1637) { 
        
	HAL_GPIO_WritePin(tm1637->DIO_GPIOx, tm1637->DIO_GPIO_Pinx, GPIO_PIN_RESET);
}

// 将DIO设置为输入
void __tm1637_dio_set_input(tm1637_t *tm1637) { 
        
	GPIO_InitTypeDef GPIO_InitStruct = { 
         0 }; //To read ACK from TM1637 and to write data to it
	GPIO_InitStruct.Pin = tm1637->DIO_GPIO_Pinx;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
	GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
	HAL_GPIO_Init(tm1637->DIO_GPIOx, &GPIO_InitStruct);
}

// 将DIO设置为输出
void __tm1637_dio_set_output(tm1637_t *tm1637) { 
        
	GPIO_InitTypeDef GPIO_InitStruct = { 
         0 }; //To read ACK from TM1637 and to write data to it
	GPIO_InitStruct.Pin = tm1637->DIO_GPIO_Pinx;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	HAL_GPIO_Init(tm1637->DIO_GPIOx, &GPIO_InitStruct);
}

// TM1637固定延时3us
void __tm1637_delay() { 
        
// __tm1637_delay_us(TM1637_DELAY_US);
	__tm1637_delay_us(TM1637_DELAY_US);
}

// 发送开始信号
void __tm1637_start(tm1637_t *tm1637) { 
        
	__tm1637_clk_high(tm1637);
	__tm1637_dio_high(tm1637);
	__tm1637_delay_us(2);
	__tm1637_dio_low(tm1637);
}

// 发送结束信号
void __tm1637_stop(tm1637_t *tm1637) { 
        

	__tm1637_clk_low(tm1637);
	__tm1637_delay_us(2);
	__tm1637_dio_low(tm1637);
	__tm1637_delay_us(2);
	__tm1637_clk_high(tm1637);
	__tm1637_delay_us(2);
	__tm1637_dio_high(tm1637);
}

void __tm1637_ack(tm1637_t *tm1637) { 
        

	__tm1637_clk_low(tm1637);
	__tm1637_delay_us(5);
	__tm1637_clk_high(tm1637);
	__tm1637_delay_us(2);
	__tm1637_clk_low(tm1637);
}

// 发送一位数据
void __tm1637_send_byte(tm1637_t *tm1637, uint8_t byte) { 
        
	uint8_t data = byte;
	for (uint8_t i = 0; i < 8; ++i) { 
        
		__tm1637_clk_low(tm1637);
		if (data & 0x01) { 
        
			__tm1637_dio_high(tm1637);
		} else { 
        
			__tm1637_dio_low(tm1637);
		}
		__tm1637_delay();
		data >>= 1;
		__tm1637_clk_high(tm1637);
		__tm1637_delay();
	}
	/* * TM1637 通过在发送第 8 位后将 DIO 从 CLK 的下降沿拉低到 CLK 的下一个下降沿来发出 ACK 信号。 * 在此期间需要将 DIO 设置为输入。 * */

	__tm1637_dio_set_input(tm1637);

	// 开始ACK信号
	__tm1637_clk_low(tm1637);
	__tm1637_delay();

	__tm1637_clk_high(tm1637);
	__tm1637_delay();

	// 结束ACK信号
	__tm1637_clk_low(tm1637);
	__tm1637_delay();

	__tm1637_dio_set_output(tm1637);
}

// 调节亮度
void __tm1637_adjust_brightness(tm1637_t *tm1637) { 
        

	if (tm1637->brightness < 0) { 
        
		tm1637->brightness = 0;
	} else if (tm1637->brightness > TM1637_MAX_BRIGHTNESS) { 
        
		tm1637->brightness = TM1637_MAX_BRIGHTNESS;
	}

	// 发送开开始信号
	__tm1637_start(tm1637);

	__tm1637_send_byte(tm1637, tm1637->brightness | 0x88);

	// 发送结束信号
	__tm1637_stop(tm1637);
}

// 向TM1637发送数据
void __tm1637_set_segment_raw_data(tm1637_t *tm1637, const uint8_t segment_idx,
		const uint8_t data) { 
        
	// 发送开开始信号
	__tm1637_start(tm1637);
	// 选择地址
	__tm1637_send_byte(tm1637, TM1637_ADDR_FIXED);
	// 发送结束信号
	__tm1637_stop(tm1637);

	// 发送数据
	// 发送开开始信号
	__tm1637_start(tm1637);
	__tm1637_send_byte(tm1637, segment_idx | 0xC0);
	__tm1637_send_byte(tm1637, data);
	// 发送结束信号
	__tm1637_stop(tm1637);

	// 调节亮度
	__tm1637_adjust_brightness(tm1637);
}

// 设置前导点
void __tm1637_set_lead_dot(tm1637_t *tm1637, const bool lead_zero) { 
        
	tm1637_set_number_lead_dot(tm1637, lead_zero, lead_zero, 0x00);
}

// 查找ASCII表码
uint8_t __tm1637_encode(uint8_t chr) { 
        
	if (chr > 127 || chr < 32) { 
        
		return 0;
	}
	return __s_ascii[chr - 32];
}

// 查询位
uint8_t __tm1637_digit_map(tm1637_t *tm1637, uint8_t digits, uint8_t digit) { 
        
	uint8_t result = digit;
	if (digits == 6) { 
        
		switch (digit) { 
        
		case 0:
			result = 2;
			break;
		case 1:
			result = 1;
			break;
		case 2:
			result = 0;
			break;
		case 3:
			result = 5;
			break;
		case 4:
			result = 4;
			break;
		case 5:
			result = 3;
			break;
		}
	}
	return result;
}

void __tm1637_delay_us(uint32_t us) { 
        
	for (int j = 0; j < us; j++) { 
        
		__NOP();
	}
}

void tm1637_init(tm1637_t *tm1637) { 
        
// dwt_init();

	__tm1637_clk_low(tm1637);
	__tm1637_delay();

	__tm1637_dio_high(tm1637);
	__tm1637_delay();

	__tm1637_clk_high(tm1637)
        标签: tm的传感器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

 锐单商城 - 一站式电子元器件采购平台  

 深圳锐单电子有限公司