文档
STM32F103ZET6 Elite Board 代码例程
本文档覆盖精英版板载各外设的驱动代码:LCD、SD卡+FATFS、SPI Flash、I2C EEPROM、DS18B20、CAN、RS485、红外遥控、蜂鸣器 PWM。
一、板级基础驱动 (BSP)
1.1 板载 LED 与 按键
/* bsp_led_key.c - 精英版板载 LED 和按键驱动 */
#include "stm32f10x.h"
/* LED 初始化 (PE2-PE5) */
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOE, &GPIO_InitStructure);
/* 初始全部熄灭 (高电平) */
GPIO_SetBits(GPIOE, GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5);
}
/* LED 宏定义 */
#define LED0 PEout(2)
#define LED1 PEout(3)
#define LED2 PEout(4)
#define LED3 PEout(5)
#define LED0_ON() GPIO_ResetBits(GPIOE, GPIO_Pin_2)
#define LED0_OFF() GPIO_SetBits(GPIOE, GPIO_Pin_2)
/* 按键初始化 (PE0-PE3) */
void KEY_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入
GPIO_Init(GPIOE, &GPIO_InitStructure);
}
/* 按键扫描(简单消抖) */
#define KEY0 GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_0)
#define KEY1 GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_1)
uint8_t KEY_Scan(void)
{
static uint8_t keyUp = 1;
if (keyUp && (KEY0 == 0 || KEY1 == 0))
{
HAL_Delay(10); // 消抖
keyUp = 0;
if (KEY0 == 0) return 1;
if (KEY1 == 0) return 2;
}
else if (KEY0 == 1 && KEY1 == 1)
{
keyUp = 1;
}
return 0;
}
1.2 蜂鸣器 PWM 驱动
/* 蜂鸣器 PB8 - TIM4_CH3 PWM */
#include "stm32f10x.h"
void BEEP_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
/* GPIO 时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
/* PB8: 复用推挽输出 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* TIM4: 72MHz / 72 = 1MHz, ARR=2000 → 500Hz */
TIM_TimeBaseStructure.TIM_Period = 2000 - 1;
TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
/* PWM 模式1 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 1000; // 50% 占空比
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC3Init(TIM4, &TIM_OCInitStructure);
TIM_Cmd(TIM4, ENABLE);
}
/* 设置蜂鸣器占空比 0-1999 */
void BEEP_SetDuty(uint16_t duty)
{
TIM_SetCompare3(TIM4, duty);
}
/* 蜂鸣器响/停 */
void BEEP_On(void) { BEEP_SetDuty(1000); }
void BEEP_Off(void) { BEEP_SetDuty(0); }
二、板载外设驱动
2.1 I2C EEPROM (AT24C02)
/* AT24C02 读写 - I2C1 PB6(SCL) PB7(SDA) */
#include "stm32f10x.h"
#define AT24C02_ADDR 0xA0 // 7位地址 1010 000x
void AT24C02_Init(void)
{
I2C_InitTypeDef I2C_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
/* PB6(SCL), PB7(SDA) - 开漏复用 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
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_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = 400000;
I2C_Init(I2C1, &I2C_InitStructure);
I2C_Cmd(I2C1, ENABLE);
}
/* 写入一个字节 */
void AT24C02_WriteByte(uint8_t addr, uint8_t data)
{
I2C_GenerateSTART(I2C1, ENABLE);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C1, AT24C02_ADDR, I2C_Direction_Transmitter);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
I2C_SendData(I2C1, addr);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_SendData(I2C1, data);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_GenerateSTOP(I2C1, ENABLE);
HAL_Delay(5); // AT24C02 写入周期 5ms
}
/* 读取一个字节 */
uint8_t AT24C02_ReadByte(uint8_t addr)
{
uint8_t data;
/* 先发送要读取的地址 */
I2C_GenerateSTART(I2C1, ENABLE);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C1, AT24C02_ADDR, I2C_Direction_Transmitter);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
I2C_SendData(I2C1, addr);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
/* 重新起始 + 读 */
I2C_GenerateSTART(I2C1, ENABLE);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C1, AT24C02_ADDR, I2C_Direction_Receiver);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
I2C_AcknowledgeConfig(I2C1, DISABLE); // NACK 结束
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
data = I2C_ReceiveData(I2C1);
I2C_GenerateSTOP(I2C1, ENABLE);
return data;
}
2.2 SPI Flash (W25Q64)
/* W25Q64 - SPI2 PB12(CS) PB13(SCK) PB14(MISO) PB15(MOSI) */
#include "stm32f10x.h"
#define W25Q_CS_LOW() GPIO_ResetBits(GPIOB, GPIO_Pin_12)
#define W25Q_CS_HIGH() GPIO_SetBits(GPIOB, GPIO_Pin_12)
/* 命令列表 */
#define W25Q_READ_ID 0x9F
#define W25Q_READ_DATA 0x03
#define W25Q_WRITE_ENABLE 0x06
#define W25Q_SECTOR_ERASE 0x20
#define W25Q_PAGE_PROGRAM 0x02
#define W25Q_READ_STATUS 0x05
void W25Q_Init(void)
{
SPI_InitTypeDef SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
/* SCK, MOSI, MISO */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* CS (软件控制) */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
W25Q_CS_HIGH();
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_Init(SPI2, &SPI_InitStructure);
SPI_Cmd(SPI2, ENABLE);
}
uint8_t SPI2_SendByte(uint8_t byte)
{
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI2, byte);
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);
return SPI_I2S_ReceiveData(SPI2);
}
/* 读取 ID */
uint32_t W25Q_ReadID(void)
{
uint32_t id = 0;
W25Q_CS_LOW();
SPI2_SendByte(W25Q_READ_ID);
id |= SPI2_SendByte(0xFF) << 16;
id |= SPI2_SendByte(0xFF) << 8;
id |= SPI2_SendByte(0xFF);
W25Q_CS_HIGH();
return id; // W25Q64 → 0xEF4017
}
/* 读取数据 */
void W25Q_Read(uint32_t addr, uint8_t *buf, uint16_t len)
{
W25Q_CS_LOW();
SPI2_SendByte(W25Q_READ_DATA);
SPI2_SendByte((addr >> 16) & 0xFF);
SPI2_SendByte((addr >> 8) & 0xFF);
SPI2_SendByte(addr & 0xFF);
for (uint16_t i = 0; i < len; i++)
buf[i] = SPI2_SendByte(0xFF);
W25Q_CS_HIGH();
}
/* 页写入(最多256字节) */
void W25Q_PageProgram(uint32_t addr, uint8_t *buf, uint16_t len)
{
W25Q_CS_LOW();
SPI2_SendByte(W25Q_WRITE_ENABLE); // 写使能
W25Q_CS_HIGH();
W25Q_CS_LOW();
SPI2_SendByte(W25Q_PAGE_PROGRAM);
SPI2_SendByte((addr >> 16) & 0xFF);
SPI2_SendByte((addr >> 8) & 0xFF);
SPI2_SendByte(addr & 0xFF);
for (uint16_t i = 0; i < len; i++)
SPI2_SendByte(buf[i]);
W25Q_CS_HIGH();
/* 等待写入完成 */
while (W25Q_ReadStatus() & 0x01);
}
uint8_t W25Q_ReadStatus(void)
{
uint8_t status;
W25Q_CS_LOW();
SPI2_SendByte(W25Q_READ_STATUS);
status = SPI2_SendByte(0xFF);
W25Q_CS_HIGH();
return status;
}
2.3 DS18B20 温度传感器
/* DS18B20 - PG11 单总线 */
#include "stm32f10x.h"
#define DS18B20_DQ PGout(11)
#define DS18B20_DQ_IN GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_11)
/* 微秒级延时 (72MHz, 非精确但单总线可接受) */
static void delay_us(uint32_t us)
{
uint32_t i;
for (i = 0; i < us * 8; i++);
}
void DS18B20_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOG, &GPIO_InitStructure);
DS18B20_DQ = 1;
}
/* 复位脉冲 + 检测存在脉冲 */
uint8_t DS18B20_Reset(void)
{
uint8_t presence;
DS18B20_DQ = 0; // 拉低 480us
delay_us(480);
DS18B20_DQ = 1; // 释放
delay_us(60);
presence = DS18B20_DQ_IN; // 检测存在脉冲
delay_us(420);
return presence; // 0 = 存在, 1 = 不存在
}
/* 写一个 bit */
void DS18B20_WriteBit(uint8_t bit)
{
DS18B20_DQ = 0;
delay_us(2);
if (bit) DS18B20_DQ = 1;
delay_us(60);
DS18B20_DQ = 1;
}
/* 写一个字节 */
void DS18B20_WriteByte(uint8_t data)
{
for (uint8_t i = 0; i < 8; i++)
DS18B20_WriteBit((data >> i) & 0x01);
}
/* 读一个 bit */
uint8_t DS18B20_ReadBit(void)
{
uint8_t bit;
DS18B20_DQ = 0;
delay_us(2);
DS18B20_DQ = 1;
delay_us(12);
bit = DS18B20_DQ_IN;
delay_us(50);
return bit;
}
/* 读一个字节 */
uint8_t DS18B20_ReadByte(void)
{
uint8_t data = 0;
for (uint8_t i = 0; i < 8; i++)
data |= (DS18B20_ReadBit() << i);
return data;
}
/* 读取温度 */
float DS18B20_ReadTemp(void)
{
uint8_t TL, TH;
int16_t temp;
DS18B20_Reset();
DS18B20_WriteByte(0xCC); // 跳过 ROM
DS18B20_WriteByte(0x44); // 启动温度转换
delay_us(750000); // 等待转换 (750ms)
DS18B20_Reset();
DS18B20_WriteByte(0xCC); // 跳过 ROM
DS18B20_WriteByte(0xBE); // 读暂存器
TL = DS18B20_ReadByte();
TH = DS18B20_ReadByte();
temp = (TH << 8) | TL;
return temp * 0.0625f; // 分辨率 12bit = 0.0625°C
}
2.4 CAN 通信
/* CAN1 - PD0(RX) PD1(TX) 经 TJA1050 */
#include "stm32f10x.h"
void CAN1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
/* PD0(RX) - 浮空输入, PD1(TX) - 复用推挽 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/* CAN 初始化 500Kbps @ 36MHz APB1 */
CAN_InitStructure.CAN_TTCM = DISABLE;
CAN_InitStructure.CAN_ABOM = ENABLE;
CAN_InitStructure.CAN_AWUM = DISABLE;
CAN_InitStructure.CAN_NART = ENABLE;
CAN_InitStructure.CAN_RFLM = DISABLE;
CAN_InitStructure.CAN_TXFP = DISABLE;
CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
CAN_InitStructure.CAN_BS1 = CAN_BS1_6tq;
CAN_InitStructure.CAN_BS2 = CAN_BS2_5tq;
CAN_InitStructure.CAN_Prescaler = 6; // 36MHz / 6 / (1+6+5) = 500Kbps
CAN_Init(CAN1, &CAN_InitStructure);
/* 过滤器:接收所有 ID */
CAN_FilterInitStructure.CAN_FilterNumber = 0;
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO0;
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);
}
/* 发送 CAN 消息 */
uint8_t CAN_SendMsg(uint32_t id, uint8_t *data, uint8_t len)
{
CanTxMsg txMsg;
txMsg.StdId = id;
txMsg.ExtId = 0;
txMsg.IDE = CAN_Id_Standard;
txMsg.RTR = CAN_RTR_Data;
txMsg.DLC = len;
for (uint8_t i = 0; i < len; i++)
txMsg.Data[i] = data[i];
uint8_t mailbox = CAN_Transmit(CAN1, &txMsg);
uint32_t timeout = 0xFFFF;
while (CAN_TransmitStatus(CAN1, mailbox) != CAN_TxStatus_Ok && timeout--)
;
return (timeout == 0) ? 0 : 1;
}
/* 接收 CAN 消息 */
uint8_t CAN_ReceiveMsg(uint32_t *id, uint8_t *data, uint8_t *len)
{
CanRxMsg rxMsg;
if (CAN_MessagePending(CAN1, CAN_FIFO0) == 0)
return 0;
CAN_Receive(CAN1, CAN_FIFO0, &rxMsg);
*id = rxMsg.StdId;
*len = rxMsg.DLC;
for (uint8_t i = 0; i < rxMsg.DLC; i++)
data[i] = rxMsg.Data[i];
return 1;
}
2.5 RS485 通信
/* RS485 - USART3 + SP3485 方向控制 PG7 */
#include "stm32f10x.h"
#define RS485_TX_EN() GPIO_SetBits(GPIOG, GPIO_Pin_7) // 发送模式
#define RS485_RX_EN() GPIO_ResetBits(GPIOG, GPIO_Pin_7) // 接收模式
void RS485_Init(uint32_t baudrate)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOG, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
/* PB10(TX), PB11(RX) */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* PG7 - 方向控制 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOG, &GPIO_InitStructure);
RS485_RX_EN(); // 默认接收模式
USART_InitStructure.USART_BaudRate = baudrate;
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_Rx | USART_Mode_Tx;
USART_Init(USART3, &USART_InitStructure);
USART_Cmd(USART3, ENABLE);
}
void RS485_Send(uint8_t *buf, uint16_t len)
{
RS485_TX_EN();
for (uint16_t i = 0; i < len; i++)
{
USART_SendData(USART3, buf[i]);
while (USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET);
}
RS485_RX_EN();
}
三、综合示例:LCD 显示传感器数据
/* 综合演示:读取 DS18B20 温度,显示在 LCD,通过串口打印,LED 闪烁 */
#include "stm32f10x.h"
#include "lcd.h" // LCD 驱动(根据具体屏幕型号)
#include <stdio.h>
int main(void)
{
float temperature;
char lcdBuf[32];
SystemInit(); // 系统初始化 72MHz
LED_Init();
KEY_Init();
BEEP_Init();
DS18B20_Init();
USART1_Init(115200); // CH340G 串口
LCD_Init();
LCD_Clear(BLACK);
LCD_ShowString(0, 0, "STM32F103ZET6", WHITE, BLACK);
LCD_ShowString(0, 16, "Elite Board", WHITE, BLACK);
printf("System Started!\r\n");
while (1)
{
temperature = DS18B20_ReadTemp();
/* LCD 显示 */
snprintf(lcdBuf, sizeof(lcdBuf), "Temp: %.1f C", temperature);
LCD_ShowString(0, 48, lcdBuf, YELLOW, BLACK);
/* 串口输出 */
printf("Temperature: %.1f C\r\n", temperature);
/* LED 闪烁 */
LED0_ON(); HAL_Delay(100); LED0_OFF();
/* 按键检测 */
if (KEY_Scan() == 1)
{
BEEP_On();
HAL_Delay(100);
BEEP_Off();
printf("Key pressed!\r\n");
}
HAL_Delay(900);
}
}
四、开发环境推荐
| 平台 | 说明 |
|---|---|
| Keil MDK-ARM | 正点原子/野火教程均基于此,兼容性最好 |
| STM32CubeIDE | 现代化 IDE,CubeMX 集成,推荐新项目 |
| IAR EWARM | 部分工业用户使用 |