1、创建基础工程,使用PA0与PA1为TM1637的时钟与数据IO
2、打开LSE、UART,配置RTC的闹钟为1秒周期

3、生成mdk工程。
4、添加TM1637的驱动:
#include "tm1637.h"
#include "NimaLTD.NimaLTD-TM1637_conf.h"
#include "stm32c092xx.h"
#include "main.h"
#include "systick_delay.h"
void _tm1637Start(void);
void _tm1637Stop(void);
void _tm1637ReadResult(void);
void _tm1637WriteByte(unsigned char b);
void _tm1637DelayUsec(unsigned int i);
void _tm1637ClkHigh(void);
void _tm1637ClkLow(void);
void _tm1637DioHigh(void);
void _tm1637DioLow(void);
void tm1637SetBrightness(char brightness);
#define CLK_PORT GPIOA
#define DIO_PORT GPIOA
#define CLK_PIN GPIO_PIN_0
#define DIO_PIN GPIO_PIN_1
#define CLK_PORT_CLK_ENABLE __HAL_RCC_GPIOA_CLK_ENABLE
#define DIO_PORT_CLK_ENABLE __HAL_RCC_GPIOA_CLK_ENABLE
const char segmentMap[] = {
0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, // 0-7
0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71, // 8-9, A-F
0x00
};
void tm1637Init(void)
{
CLK_PORT_CLK_ENABLE();
DIO_PORT_CLK_ENABLE();
GPIO_InitTypeDef g = {0};
g.Pull = GPIO_PULLUP;
g.Mode = GPIO_MODE_OUTPUT_OD; // OD = open drain
g.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
g.Pin = CLK_PIN;
HAL_GPIO_Init(CLK_PORT, &g);
g.Pin = DIO_PIN;
HAL_GPIO_Init(DIO_PORT, &g);
tm1637SetBrightness(8);
}
void tm1637DisplayDecimal(int v, int displaySeparator)
{
unsigned char digitArr[4];
for (int i = 0; i < 4; ++i) {
digitArr[i] = segmentMap[v % 10];
if (i == 2 && displaySeparator) {
digitArr[i] |= 1 << 7;
}
v /= 10;
}
_tm1637Start();
_tm1637WriteByte(0x40);
_tm1637ReadResult();
_tm1637Stop();
_tm1637Start();
_tm1637WriteByte(0xc0);
_tm1637ReadResult();
for (int i = 0; i < 4; ++i) {
_tm1637WriteByte(digitArr[3 - i]);
_tm1637ReadResult();
}
_tm1637Stop();
}
void TM1637_DisplayTime(RTC_TimeTypeDef sTime, int displaySeparator)
{
unsigned char digitArr[4];
digitArr[0] = segmentMap[sTime.Minutes / 10];
digitArr[1] = segmentMap[sTime.Minutes % 10];
digitArr[2] = segmentMap[sTime.Seconds / 10];
digitArr[3] = segmentMap[sTime.Seconds % 10];
_tm1637Start();
_tm1637WriteByte(0x40);
_tm1637ReadResult();
_tm1637Stop();
_tm1637Start();
_tm1637WriteByte(0xc0);
_tm1637ReadResult();
for (int i = 0; i < 4; ++i) {
_tm1637WriteByte(digitArr[3 - i]);
_tm1637ReadResult();
}
_tm1637Stop();
}
// Valid brightness values: 0 - 8.
// 0 = display off.
void tm1637SetBrightness(char brightness)
{
_tm1637Start();
_tm1637WriteByte(0x87 + brightness);
_tm1637ReadResult();
_tm1637Stop();
}
void _tm1637Start(void)
{
_tm1637ClkHigh();
_tm1637DioHigh();
_tm1637DelayUsec(2);
_tm1637DioLow();
}
void _tm1637Stop(void)
{
_tm1637ClkLow();
_tm1637DelayUsec(2);
_tm1637DioLow();
_tm1637DelayUsec(2);
_tm1637ClkHigh();
_tm1637DelayUsec(2);
_tm1637DioHigh();
}
void _tm1637ReadResult(void)
{
_tm1637ClkLow();
_tm1637DelayUsec(5);
// while (dio); // We're cheating here and not actually reading back the response.
_tm1637ClkHigh();
_tm1637DelayUsec(2);
_tm1637ClkLow();
}
void _tm1637WriteByte(unsigned char b)
{
for (int i = 0; i < 8; ++i) {
_tm1637ClkLow();
if (b & 0x01) {
_tm1637DioHigh();
}
else {
_tm1637DioLow();
}
_tm1637DelayUsec(3);
b >>= 1;
_tm1637ClkHigh();
_tm1637DelayUsec(3);
}
}
void _tm1637DelayUsec(unsigned int i)
{
delay_us(i);
}
void _tm1637ClkHigh(void)
{
HAL_GPIO_WritePin(CLK_PORT, CLK_PIN, GPIO_PIN_SET);
}
void _tm1637ClkLow(void)
{
HAL_GPIO_WritePin(CLK_PORT, CLK_PIN, GPIO_PIN_RESET);
}
void _tm1637DioHigh(void)
{
HAL_GPIO_WritePin(DIO_PORT, DIO_PIN, GPIO_PIN_SET);
}
void _tm1637DioLow(void)
{
HAL_GPIO_WritePin(DIO_PORT, DIO_PIN, GPIO_PIN_RESET);
}
在主函数中周期进行显示时间,显示完后关闭一次TM1637显示,再开启显示。这样就可以达到降低功耗:
/* USER CODE BEGIN 2 */
SysTick_Init();
tm1637Init();
// Optionally set brightness. 0 is off. By default, initialized to full brightness.
tm1637SetBrightness(1);
// Display the value "1234" and turn on the `:` that is between digits 2 and 3.
RTC_TimeTypeDef sTime = {0};
RTC_DateTypeDef sDate = {0};
// RTC_AlarmConfig(1);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if(flag)
{
flag = !flag;
tm1637SetBrightness(1);
HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
/* Get the RTC current Date */
HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);
shownum = (sTime.Minutes*100) + sTime.Seconds;
tm1637DisplayDecimal(shownum, 1);
}
else
{
flag = !flag;
tm1637SetBrightness(0);
}
HAL_PWR_EnterSTOPMode(PWR_MAINREGULATOR_ON, PWR_STOPENTRY_WFI);
【测试效果】
在关闭显示时,整个系统可以隆到0.7毫安,在打开数码管显示时,电流为1.5MA。感觉整体的电流都是给数码管用去了。
通过JP5来测试STM32C092的工作电流是只有0.08mA的工作电流,因此如果有LCD的显示器,那做为低功耗的时钟是非常好的。