STM32实现简单的电子钟

以下是一个使用STM32实现简单电子钟的代码案例:

首先,我们需要准备以下材料和工具:

  • STM32开发板(例如STM32F103C8T6)
  • LCD显示屏(例如16x2字符LCD)
  • 电位器(调节对比度)
  • 杜邦线
  • USB串口转TTL模块(可选,用于调试)

接下来,我们将详细介绍如何实现一个简单的电子钟。

  1. 硬件连接:
  • 将STM32开发板与LCD显示屏连接:
    • 将STM32的GND引脚连接到LCD的GND引脚。
    • 将STM32的3.3V引脚连接到LCD的VCC引脚。
    • 将STM32的PB6引脚(SCL)连接到LCD的SCL引脚。
    • 将STM32的PB7引脚(SDA)连接到LCD的SDA引脚。
  • 将电位器的中间引脚连接到STM32的PA0引脚,将两侧引脚分别连接到STM32的3.3V和GND引脚。
  1. 硬件初始化:
  • 在STM32上连接一个USB串口转TTL模块,用于调试打印信息(可选)。
  • 在STM32上连接一个外部晶振,并配置时钟源为外部晶振。
  • 配置STM32的GPIO引脚模式和推挽输出。
  1. 软件初始化:
  • 使用STM32的标准外设库(StdPeriph Lib)进行初始化。
  • 配置串口用于调试打印信息(可选)。
  • 配置I2C总线,并初始化LCD显示屏。
  1. 实现电子钟功能:
  • 使用RTC模块进行时间管理。
  • 使用定时器模块产生1秒的时钟中断。
  • 在时钟中断处理函数中更新时间,并在LCD上显示当前时间。

下面是一个示例代码,用于实现上述功能:

#include "stm32f10x.h"
#include "stm32f10x_rtc.h"
#include "stm32f10x_i2c.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_tim.h"
#include "stm32f10x_usart.h"

// 定义RTC和定时器的全局变量
RTC_InitTypeDef RTC_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

// LCD显示屏的I2C地址
#define LCD_I2C_ADDRESS 0x27

// LCD命令定义
#define LCD_CMD_CLEAR_DISPLAY 0x01
#define LCD_CMD_RETURN_HOME 0x02
#define LCD_CMD_DISPLAY_ON 0x0C
#define LCD_CMD_DISPLAY_OFF 0x08
#define LCD_CMD_ENTRY_MODE_SET 0x06

// 调试串口定义(可选)
#define DEBUG_USART USART1

// 初始化调试串口(可选)
void initDebugUSART() {
    USART_InitTypeDef USART_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;

    // 使能USARTx和GPIOA的时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);

    // 配置USART Tx引脚为复用推挽输出
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 配置USART Rx引脚为浮空输入
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 使用USART_InitStruct初始化USARTx
    USART_InitStructure.USART_BaudRate = 9600;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Tx;
    USART_Init(DEBUG_USART, &USART_InitStructure);

    // 使能USARTx
    USART_Cmd(DEBUG_USART, ENABLE);
}

// 通过调试串口打印调试信息(可选)
void debugPrint(const char *str) {
    const char *ptr = str;
    while (*ptr != '\0') {
        USART_SendData(DEBUG_USART, *ptr++);
        // 等待发送完成
        while (USART_GetFlagStatus(DEBUG_USART, USART_FLAG_TXE) == RESET);
    }
}

// 初始化I2C总线
void initI2C() {
    I2C_InitTypeDef I2C_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;

    // 使能GPIOB和I2C1的时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);

    // 配置GPIOB的引脚为开漏输出
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    // 使用I2C_InitStruct进行I2C初始化配置
    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
    I2C_InitStructure.I2C_OwnAddress1 = 0x00;
    I2C_InitStructure.I2C_Ack = I2C_Ack_Disable;
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_InitStructure.I2C_ClockSpeed = 400000;
    I2C_Init(I2C1, &I2C_InitStructure);

    // 使能I2C1总线
    I2C_Cmd(I2C1, ENABLE);
}

// 发送命令到LCD
void sendLCDCommand(uint8_t command) {
    I2C_SendData(I2C1, 0x00);
    while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS);
    I2C_SendData(I2C1, command);
    while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS);
}

// 初始化LCD显示屏
void initLCD() {
    sendLCDCommand(0x30);
    sendLCDCommand(0x30);
    sendLCDCommand(0x30);
    sendLCDCommand(0x20);
    sendLCDCommand(LCD_CMD_DISPLAY_OFF);
    sendLCDCommand(LCD_CMD_CLEAR_DISPLAY);
    sendLCDCommand(LCD_CMD_ENTRY_MODE_SET);
    sendLCDCommand(LCD_CMD_DISPLAY_ON);
}

// 在LCD显示屏上显示一行文本
void printLCDLine(uint8_t line, const char *str) {
    sendLCDCommand(0x80 | (0x00 + line * 0x40));
    while (*str != '\0') {
        I2C_SendData(I2C1, 0x40);
        while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS);
        I2C_SendData(I2C1, *str++);
        while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS);
    }
}

int main(void) {
    // 初始化系统时钟和中断向量表
    SystemInit();

    // 初始化调试串口(可选)
    initDebugUSART();

    // 初始化I2C总线
    initI2C();

    // 初始化LCD显示屏
    initLCD();

    // 配置RTC时钟源为外部晶振
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
    PWR_BackupAccessCmd(ENABLE);
    RCC_BackupResetCmd(ENABLE);
    RCC_BackupResetCmd(DISABLE);
    RCC_LSEConfig(RCC_LSE_ON);
    while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);

    // 配置RTC初始化参数
    RTC_InitStructure.RTC_AsynchPrediv = 0x7F;
    RTC_InitStructure.RTC_SynchPrediv = 0x0138;
    RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;
    RTC_Init(&RTC_InitStructure);

    // 配置RTC时钟源为LSE
    RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
    RCC_RTCCLKCmd(ENABLE);

    // 等待RTC准备好
    RTC_WaitForSynch

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大黄鸭duck.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值