Initial import of STM32 IoT sensor node

This commit is contained in:
yzfh
2026-10-19 15:47:18 +08:00
commit a51794b022
100 changed files with 46274 additions and 0 deletions
+63
View File
@@ -0,0 +1,63 @@
#include "adc.h"
// ADC1 初始化
void adc1_init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
ADC_InitTypeDef ADC_InitStruct;
// 使能 ADC 和 PC0 的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_ADC1, ENABLE);
// 初始化 PC0 为模拟输入
// 模拟输入
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
GPIO_Init(GPIOC, &GPIO_InitStruct);
// 配置 ADC 的时钟主频为 12MHz(72M 六分频)
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
// 初始化 AADC
// 独立模式
ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;
// 扫描模式(禁用)
ADC_InitStruct.ADC_ScanConvMode = DISABLE;
// 连续转换(禁用)
ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;
// 外部转换出发源(禁用),使用软件出发
ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
// 右对齐方式
ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
// 通道个数(1 个通道)
ADC_InitStruct.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStruct);
// 使能 ADC
ADC_Cmd(ADC1,ENABLE);
// 复位校准(初次使用必须使用校准)
ADC_ResetCalibration(ADC1);
// 等待复位校准结束
while (ADC_GetResetCalibrationStatus(ADC1));
// 开始校准
ADC_StartCalibration(ADC1);
// 等待校准结束
while (ADC_GetCalibrationStatus(ADC1));
// 设置成软件触发转换模式
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}
// ADC 转换取值
// channal 表示通道
uint16_t adc1_get_value(uint8_t channal)
{
// 设置规则通道的转换配置,采样周期为 239.5个 ADC 时钟周期
ADC_RegularChannelConfig(ADC1, channal, 1, ADC_SampleTime_239Cycles5);
// 开始软件转换
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
// 返回转换结果
return ADC_GetConversionValue(ADC1);
}
+19
View File
@@ -0,0 +1,19 @@
#ifndef __ADC_H
#define __ADC_H
/*
* ADC 通道 PC0/ADC_IN10
*/
#include <stm32f10x_conf.h>
// ADC1 初始化
void adc1_init(void);
// ADC 转换取值
// channal 表示通道
uint16_t adc1_get_value(uint8_t channal);
#endif // __ADC_H
+40
View File
@@ -0,0 +1,40 @@
#include "beep.h"
#include "bitband.h"
// 蜂鸣器初始化
void beep_init(void)
{
// 定义一个 GPIO 初始化啊的结构体
GPIO_InitTypeDef GPIO_InitStruct;
// 初始化时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOA, ENABLE);
// 将 PC8 和 PC9 设置成上拉输入 1000
// up 上拉
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
// 针脚
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7;
// 输出速度
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStruct);
}
// 蜂鸣器开
void beep_on(void)
{
// GPIOC_ODR |= (0x1 << 7);
PCOut(7) = 1;
}
// 蜂鸣器关
void beep_off(void)
{
// GPIOC_ODR &= ~(0x1 << 7);
PCOut(7) = 0;
}
// 获取蜂鸣器状态,返回 0 为关,1 为开
int beep_get_status(void)
{
return (GPIOC->ODR & (0x1 << 7)) ? 1 : 0;
}
+24
View File
@@ -0,0 +1,24 @@
#ifndef __BEEP_H
#define __BEEP_H
/*
* 蜂鸣器管脚: PC7
* 根据电路原理图:
* 输出高电平:响
* 输出低电平:不响
*/
#include <stm32f10x_conf.h>
#define GPIOC_CRL *(volatile unsigned int *)(0x40011000 + 0x00)
#define GPIOC_ODR *(volatile unsigned int *)(0x40011000 + 0x0C)
// 蜂鸣器初始化
void beep_init(void);
// 蜂鸣器开
void beep_on(void);
// 蜂鸣器关
void beep_off(void);
// 获取蜂鸣器状态,返回 0 为关,1 为开
int beep_get_status(void);
#endif // __BEEP_H
+48
View File
@@ -0,0 +1,48 @@
#ifndef __BITBAND_H
#define __BITBAND_H
#include <stm32f10x_conf.h>
// 计算位带地址的宏,addr表示实际地址,
// bitnum表示实际地址位的编号
// 0x2000 0101 - 5 ---> 0x2202 0214
#define BITBAND(addr, bitnum) \
((addr&0xF0000000) + 0x2000000 + \
((addr & 0xFFFFF) << 5) + (bitnum << 2))
#define MEM_ADDR(addr) *(volatile unsigned int *)(addr)
// 根据实际地址和位编号,返回位带的地址的指针并解引用。
#define BIT_BAND(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
#define GPIOA_IDR_ADDR (GPIOA_BASE + 0x08)
#define GPIOA_ODR_ADDR (GPIOA_BASE + 0x0C)
#define GPIOB_IDR_ADDR (GPIOB_BASE + 0x08)
#define GPIOB_ODR_ADDR (GPIOB_BASE + 0x0C)
#define GPIOC_IDR_ADDR (GPIOC_BASE + 0x08)
#define GPIOC_ODR_ADDR (GPIOC_BASE + 0x0C)
#define GPIOD_IDR_ADDR (GPIOD_BASE + 0x08)
#define GPIOD_ODR_ADDR (GPIOD_BASE + 0x0C)
#define GPIOE_IDR_ADDR (GPIOE_BASE + 0x08)
#define GPIOE_ODR_ADDR (GPIOE_BASE + 0x0C)
#define PAOut(n) BIT_BAND(GPIOA_ODR_ADDR, n)
#define PAIn(n) BIT_BAND(GPIOA_IDR_ADDR, n)
#define PBOut(n) BIT_BAND(GPIOB_ODR_ADDR, n)
#define PBIn(n) BIT_BAND(GPIOB_IDR_ADDR, n)
#define PCOut(n) BIT_BAND(GPIOC_ODR_ADDR, n)
#define PCIn(n) BIT_BAND(GPIOC_IDR_ADDR, n)
#define PDOut(n) BIT_BAND(GPIOD_ODR_ADDR, n)
#define PDIn(n) BIT_BAND(GPIOD_IDR_ADDR, n)
#define PEOut(n) BIT_BAND(GPIOE_ODR_ADDR, n)
#define PEIn(n) BIT_BAND(GPIOE_IDR_ADDR, n)
#endif // __BITBAND_H
+52
View File
@@ -0,0 +1,52 @@
#include "button.h"
// 初始化按键的 IO 针脚
void button_init(void)
{
// 定义一个 GPIO 初始化啊的结构体
GPIO_InitTypeDef GPIO_InitStruct;
// 初始化时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOA, ENABLE);
// 将 PC8 和 PC9 设置成上拉输入 1000
// up 上拉
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
// 针脚
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_8;
// 输出速度
// GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStruct);
// 将 PA0 设置成下拉输入
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPD;
// 针脚
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
// 输出速度
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
}
// 获取某一个按键 nu 的状态
// 返回 1 按下, 返回 0 抬起
int button_status(int nu)
{
int status = 0;
switch (nu)
{
case 0:
status = !GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_9);
break;
case 1:
status = !GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_8);
break;
case 2:
status = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0);
break;
default:
break;
}
return status;
}
+30
View File
@@ -0,0 +1,30 @@
#ifndef __BUTTON_H
#define __BUTTON_H
/*
* ---按键-----+--PIN--+---输入方式---+--CNF 位的值--+--MODE 位的值--+--按下状态--
* KEY0 | PC9 | 上拉输入 | 10 | 00 | 0
* KEY1 | PC8 | 上拉输入 | 10 | 00 | 0
* KEY2(WK_UP) | PA0 | 下拉输入 | 10 | 00 | 1
*/
#include <stm32f10x_conf.h>
// PC 组针脚控制寄存器
// #define GPIOC_CRH *(volatile unsigned int *)(0x40011000 + 0x04)
// #define GPIOC_IDR *(volatile unsigned int *)(0x40011000 + 0x08)
// #define GPIOC_ODR *(volatile unsigned int *)(0x40011000 + 0x0c)
// PA 组针脚控制寄存器
// #define GPIOA_CRL *(volatile unsigned int *)(0x40010800 + 0x00)
// #define GPIOA_IDR *(volatile unsigned int *)(0x40010800 + 0x08)
// #define GPIOA_ODR *(volatile unsigned int *)(0x40010800 + 0x0c)
// 初始化按键的 IO 针脚
void button_init(void);
// 获取某一个按键 nu 的状态
// 返回 1 按下, 返回 0 抬起
int button_status(int nu);
#endif // __BUTTON_H
+93
View File
@@ -0,0 +1,93 @@
#include "delay.h"
//利用系统滴答定时,编写的延时函数
static u8 fac_us=0; //us延时倍乘数
static u16 fac_ms=0; //ms延时倍乘数
/****************************************************************************
* 名 称: delay_init()
* 功 能:延时函数初始化
* 入口参数:无
* 返回参数:无
* 说 明:
****************************************************************************/
void delay_init(void)
{
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
//为系统定时器选择时钟为 HCLK 8分频 72MHz / 8 = 9MHz
fac_us = SYSCLK / 8;
//微妙的倍乘数 = 72 / 8 = 9
//X * fac_us就相当于有X个微妙
fac_ms = (u16)fac_us * 1000;
//每个ms需要的systick时钟数(1ms = 1000us),所以fac_us*1000
//X * fac_ms就相当于有X个毫妙
}
/****************************************************************************
* 名 称: void delay_us(u32 nus)
* 功 能:延时nus
* 入口参数:要延时的微妙数
* 返回参数:无
* 说 明:nus的值,不要大于1864135us
****************************************************************************/
/*
通过相关手册我们了解到,备份值寄存器和当前值寄存器的值最大为16M - 1
我们的微妙级的延时函数的倍乘数为9所以16M - 1 / 9 = 1864135
*/
void delay_us(u32 nus)
{
u32 midtime; //保存寄存器的状态
SysTick->LOAD = nus * fac_us; //时间加载(相当于有nus个微妙)
SysTick->VAL = 0x00; //清空计数器
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; //使能系统定时器计数
do
{
midtime = SysTick->CTRL;
}
while((midtime & 0x01) && !(midtime & (1 << 16)));//等待时间到达
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; //关闭计数器
SysTick->VAL = 0X00; //清空计数器
}
/****************************************************************************
* 名 称: void delay_xms(u16 nms)
* 功 能:延时nms
* 入口参数:要延时的毫妙数
* 返回参数:无
* 说 明:SysTick->LOAD为24位寄存器,所以,最大延时为: nms<=0xffffff*8*1000/SYSCLK
对9M条件下,nms<=1864ms
****************************************************************************/
void delay_xms(u16 nms)
{
u32 midtime;
SysTick->LOAD = (u32)nms*fac_ms; //时间加载(SysTick->LOAD为24bit)
SysTick->VAL = 0x00; //清空计数器
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; //开始倒数
do
{
midtime = SysTick->CTRL;
}
while((midtime & 0x01) && !(midtime & (1 << 16)));//等待时间到达
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; //关闭计数器
SysTick->VAL = 0X00; //清空计数器
}
/****************************************************************************
* 名 称: void delay_ms(u16 nms)
* 功 能:延时nms
* 入口参数:要延时的毫妙数
* 返回参数:无
* 说 明:nms:0~65535
****************************************************************************/
void delay_ms(u16 nms)
{
u8 repeat = nms / 540; //记录有多少个整的540ms
u16 remain = nms % 540; //记录有多少个不够540ms
while(repeat)
{
delay_xms(540);
repeat--;
}
if(remain)delay_xms(remain);
}
+45
View File
@@ -0,0 +1,45 @@
#ifndef __DELAY_H
#define __DELAY_H
#include "stm32f10x_conf.h"
#define SYSCLK 72 //系统时钟的基数(注:是72而不是72M)
typedef uint32_t u32;
typedef uint16_t u16;
typedef uint8_t u8;
void delay_init(void); //延时函数的初始化
void delay_ms(u16 nms); //毫秒级的延时函数(参数为毫秒数)
void delay_us(u32 nus); //微妙级的延时函数(参数为微妙数)
#endif
+117
View File
@@ -0,0 +1,117 @@
#include "dht11.h"
#include "bitband.h"
#include "systick.h"
#define DATA_OUT PCOut(10)
#define DATA_IN PCIn(10)
// 将连接 DHT11 的管脚设置为浮空输入(变为输入模式)
static void dht11_set_input(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
// 浮空输入模式
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOC, &GPIO_InitStruct);
}
// 将连接 DHT11 的管脚设置为推挽输出或开漏输出(变为输出模式)
static void dht11_set_output(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
// 开漏输出模式
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStruct);
}
// 将连接 DHT11 的管脚设置位输出状态为 s(0, 1)
static void dht11_set_output_status(int s)
{
dht11_set_output();
DATA_OUT = s ? 1 : 0;
}
// 将连接 DHT11 的管脚设置位输出状态为 s(0, 1)
static int dht11_get_input_status()
{
dht11_set_input();
return DATA_IN;
}
// 初始化 DHT11 控制器
void dht11_init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
// 设置位浮空输入
dht11_set_input();
// 初始化时钟(防止主函数内忘记初始化)
systick_init();
}
// 获取 DHT11 传感器的 40位 数据,放入buf中
// 成功返回 1. 失败返回 0
int dht11_get_values(u8 buf[5])
{
u8 status = 0;
u8 time = 0;
// 用于记录缓冲区地址
int i;
int bit;
u8 temp = 0;
// 发送起始信号
// 先保证数据线位高电平
dht11_set_output_status(1);
// 发送起始信号
dht11_set_output_status(0);
delay_ms(20);
// 拉高
dht11_set_output_status(1);
delay_us(20);
// 等待 40us,如果有数据线没被拉低,则说明设备不存在
do
{
// 获取输入的状态
status = dht11_get_input_status();
delay_us(2);
time++;
} while (status == 1 && time < 20);
if (temp >= 20)
{
return 0;
}
// 等待转为高电平
while (!dht11_get_input_status());
// 读取 40bit 数据
// i 表示字节的缩影
for (i = 0; i < 5; i++)
{
// temp 表示正在读取的一个字节
temp = 0;
for (bit = 0; bit < 8; bit++)
{
// 等待转为低电平
while(dht11_get_input_status());
// 等待转为高电平
while(!dht11_get_input_status());
delay_us(40);
// 将 40us 后的电平状态放入 temp 的最低位
temp <<= 1;
temp |= dht11_get_input_status();
}
// 将获取到的一个字节填入数组中
buf[i] = temp;
}
// 主机拉高
dht11_set_output_status(1);
return 1;
}
+16
View File
@@ -0,0 +1,16 @@
#ifndef __DHT11_H
#define __DHT11_H
/*
* DHT11 的数据线管脚 DATA --> PC10
*/
#include <stm32f10x_conf.h>
// 初始化 DHT11 控制器
void dht11_init(void);
// 获取 DHT11 传感器的 40位 数据,放入buf中
// 成功返回 1. 失败返回 0
int dht11_get_values(u8 buf[5]);
#endif // __DHT11_H
+116
View File
@@ -0,0 +1,116 @@
#include "eeprom.h"
#include "gpio_iic.h"
#include "stdio.h"
#include "systick.h"
static u8 dev_addr = (0x50 << 1);
// EEPROM 初始化
void eeprom_init(void)
{
iic_init(); // 调用iic初始化
}
// 在addr地址写入一个字节data
void eeprom_write_one_byte(u8 addr, u8 data)
{
int ack_ret;
iic_start();
iic_send_byte(dev_addr);
ack_ret = iic_wait_ack();
if (ack_ret)
{
printf("device:%02x,return NACK\r\n", addr);
iic_stop();
return;
}
iic_send_byte(addr);
iic_wait_ack();
iic_send_byte(data);
iic_wait_ack();
iic_stop();
delay_ms(5);
}
// 从向设备的addr地址写入size个字节
void eeprom_write_bytes(u8 addr, const u8 *buf, u8 size)
{
int i;
iic_start();
// 发送设备地址(写)
iic_send_byte(dev_addr);
iic_send_ack();
// 发送写入数据的地址
iic_send_byte(addr);
iic_send_ack();
// 发送 size 个字节的数据
for (i = 0; i < size; i++)
{
iic_send_byte(buf[i]);
iic_wait_ack();
}
// 发送完数据,发送停止信号
iic_stop();
}
// 在当前位置读取一个字节,然后地址后移一个字节
u8 eeprom_read_cur_byte(void)
{
u8 value = 0;
iic_start();
// 读方式(等同于 dev_addr | 0x01)
iic_send_byte(dev_addr + 1);
iic_wait_ack();
// 接收数据并回复非应答
value = iic_recv_byte(0);
iic_stop();
return value;
}
// 从addr地址随机读取一个字节
u8 eeprom_read_one_byte(u8 addr)
{
u8 data = 1;
iic_start();
iic_send_byte(dev_addr);
iic_wait_ack();
iic_send_byte(addr);
iic_wait_ack();
iic_start();
iic_send_byte(dev_addr | 0x01);
iic_wait_ack();
data = iic_recv_byte(0);
iic_stop();
return data;
}
// 从addr地址开始读取size分字节放入buf
void eeprom_read_bytes(u8 addr, u8 *buf, u8 size)
{
u8 data = 0;
int i;
iic_start();
iic_send_byte(dev_addr);
iic_wait_ack();
iic_send_byte(addr);
iic_wait_ack();
iic_start();
iic_send_byte(dev_addr | 0x01);
iic_wait_ack();
for ( i = 0; i < size; i++)
{
// 最后一个数据给非应答
if (i + 1 == size)
{
// 读取数据并返回非应答
data = iic_recv_byte(0);
} else {
data = iic_recv_byte(1);
}
// 放入缓冲区
buf[i] = data;
}
data = iic_recv_byte(0);
iic_stop();
}
+23
View File
@@ -0,0 +1,23 @@
#ifndef __EEPROM_H
#define __EEPROM_H
#include <stm32f10x_conf.h>
//EEPROM 初始化
void eeprom_init(void);
//在addr地址写入一个字节data
void eeprom_write_one_byte(u8 addr,u8 data);
//从向设备的addr地址写入size个字节
void eeprom_write_bytes(u8 addr,const u8*buf,u8 size);
//在当前位置读取一个字节,然后地址后移一个字节
u8 eeprom_read_cur_byte(void);
//从addr地址随机读取一个字节
u8 eeprom_read_one_byte(u8 addr);
//从addr地址开始读取size分字节放入buf
void eeprom_read_bytes(u8 addr,u8 *buf,u8 size);
#endif //__EEPROM_H
+332
View File
@@ -0,0 +1,332 @@
#include <stdio.h>
#include <string.h>
#include "systick.h"
#include "queue.h"
#include "esp8266.h"
/* USART2管脚定义
TX PA2
RX PA3
*/
// 创建USART2的接收队列。
static struct queue usart2_rx_queue;
// 重置 Wifi 模块的传输模式为工作站模式,成功返回1,失败返回0.
int esp8266_reset_module(void)
{
char buf[100];
// 重置Wifi模块
esp8266_send_cmd("AT+RST");
delay_ms(1000);
delay_ms(1000);
esp8266_clear_read_buf();
// 设置Wifi的工作模式为 工作站模式
esp8266_send_cmd("AT+CWMODE=1");
if (esp8266_read_response(buf, sizeof(buf), 1000) == 0)
return 0;
if (strstr(buf, "OK"))
return 1;
return 0;
}
// ESP8266初始化
void esp8266_init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
USART_InitTypeDef USART_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
// 初始化接收队列
queue_init(&usart2_rx_queue);
// 使能PA2和 PA3的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// 使能 USART2外设时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
// 设置PA2 为发送管脚
// 复用推挽输出
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// 设置PA3 为接受管脚
// 悬空输入
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// 初始化 USART1控制器
USART_InitStruct.USART_BaudRate = 115200; // 设置波特率
USART_InitStruct.USART_WordLength = USART_WordLength_8b; // 字长8bit
USART_InitStruct.USART_StopBits = USART_StopBits_1; // 停止位1bit
USART_InitStruct.USART_Parity = USART_Parity_No; // 校验位(无)
USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 收发
USART_InitStruct.USART_HardwareFlowControl =
USART_HardwareFlowControl_None; // 硬件流控制(无)
USART_Init(USART2, &USART_InitStruct);
// 使能串口2
USART_Cmd(USART2, ENABLE);
// 初始化接收中断
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
// 清理中断标志位
USART_ClearFlag(USART2, USART_FLAG_TC);
NVIC_InitStruct.NVIC_IRQChannel = USART2_IRQn; // 中断通道
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
// 开启接收寄存器非空中断
// USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
if (0 == esp8266_reset_module())
printf("reset Wifi module Error!\r\n");
}
// 编写冲断处理函数
void USART2_IRQHandler(void)
{
uint8_t ch;
// 如果是接收寄存器非空中断,则读取数据
if (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
{
ch = USART_ReceiveData(USART2);
// 将接收到的字符放入接收队列,如果队列已满会丢掉此字符
queue_enqueue(&usart2_rx_queue, ch);
}
}
// 用于串口发送一个字节的数据
void usart2_put_char(uint8_t ch)
{
USART_SendData(USART2, ch); // 发送数据
// 等待发送数据完毕
while (USART_GetFlagStatus(USART2, USART_FLAG_TC) != SET)
;
}
// ESP8266通过USART2发送字符串数据
void esp8266_send_string(const char *buf)
{
const char *pchar;
for (pchar = buf; *pchar; ++pchar)
usart2_put_char((uint8_t)*pchar);
}
// ESP8266通过USART2发送AT指令
void esp8266_send_cmd(const char *cmd)
{
esp8266_send_string(cmd);
esp8266_send_string("\r\n");
}
// 从USART2 读取相应字符串放入 buf,总等待时长timeout_ms毫秒ms,
// 直到timeout_ms耗尽为0才返回
int esp8266_read_response(char *buf, int buf_size, int timeout_ms)
{
int i = 0;
int ch = '\0';
// 等待接收数据,最大等待 timeout_ms 微妙
while (--timeout_ms)
{
if (queue_is_empty(&usart2_rx_queue))
delay_ms(1);
else
break;
}
if (timeout_ms == 0) // 超时返回
return 0;
// 接收数据
while (i < buf_size - 1 && timeout_ms > 0)
{
if (queue_is_empty(&usart2_rx_queue))
{
delay_ms(1); // 继续等待,直至timeout_ms为零
timeout_ms--;
}
else
{
queue_dequeue(&usart2_rx_queue, &ch);
buf[i] = ch;
i++;
}
}
buf[i] = '\0'; // 添加尾零后返回数据
// debug print for response
printf("esp8266_resp: %s\r\n", buf);
return i;
// for (i = 0; i < buf_size -1; i++) {
// queue_dequeue(&usart2_rx_queue, &ch);
// buf[i] = ch;
// if (queue_is_empty(&usart2_rx_queue))
// delay_ms(1);
// if (queue_is_empty(&usart2_rx_queue)) {
// i++;
// buf[i] = '\0';
// return i;
// }
// }
// return i;
}
// ESP8266 连接 Wifi,成功返回1,失败返回0
int esp8266_connect_wifi(const char *ssid, const char *passwd)
{
char buf[100];
// 拼接命令字符串
sprintf(buf, "AT+CWJAP=\"%s\",\"%s\"", ssid, passwd);
esp8266_clear_read_buf(); // 清空读缓冲。
esp8266_send_cmd(buf);
// WiFi 连接可能需要较长时间,延长超时到 15s
if (0 == esp8266_read_response(buf, sizeof(buf), 15000))
return 0;
if (strstr(buf, "OK") != NULL)
return 1;
// print returned response for debugging
printf("esp8266_connect_wifi failed resp: %s\r\n", buf);
return 0;
}
// ESP8266 作为客户端远程 TCP 连接。成功返回1,失败返回0
int esp8266_tcp_connect(const char *ip, uint16_t port)
{
char buf[100];
// 拼接命令字符串
sprintf(buf, "AT+CIPSTART=\"TCP\",\"%s\",%d", ip, port);
esp8266_clear_read_buf(); // 清空读缓冲。
esp8266_send_cmd(buf);
if (0 == esp8266_read_response(buf, sizeof(buf), 8000))
return 0;
// some firmwares may return "OK" or "ALREADY" or "ERROR"
if (strstr(buf, "OK") != NULL || strstr(buf, "ALREADY") != NULL)
return 1;
printf("esp8266_tcp_connect resp: %s\r\n", buf);
return 0;
}
// 关闭tcp 连接
void esp8266_tcp_close(void)
{
esp8266_send_cmd("AT+CIPCLOSE");
delay_ms(1000);
esp8266_clear_read_buf(); // 清空读缓冲。
}
// ESP8266 TCP 协议发送数据,返回写入的字节数,0表示失败
int esp8266_write(const char *data, uint16_t len)
{
char buf[100];
// 拼接命令字符串
sprintf(buf, "AT+CIPSEND=%d", len);
esp8266_clear_read_buf(); // 清空读缓冲。
esp8266_send_cmd(buf);
// wait for prompt '>' (and optionally OK). Allow longer timeout for some modules.
if (0 == esp8266_read_response(buf, sizeof(buf), 8000))
return 0;
// If there's no '>' in the response, but OK is present, try to read again shortly
if (strstr(buf, ">") == NULL) {
if (strstr(buf, "OK") != NULL) {
// try a short additional read to get the '>' prompt
if (0 == esp8266_read_response(buf, sizeof(buf), 2000) || strstr(buf, ">") == NULL) {
printf("esp8266_write: no '>' prompt after CIPSEND, resp: %s\r\n", buf);
return 0;
}
} else {
printf("esp8266_write: unexpected resp to CIPSEND: %s\r\n", buf);
return 0;
}
}
// send payload
esp8266_send_string(data);
// wait for SEND OK (some firmwares reply with SEND OK)
if (0 == esp8266_read_response(buf, sizeof(buf), 5000)) {
// no response, still consider write as attempted
return len;
}
if (strstr(buf, "SEND OK") != NULL || strstr(buf, "OK") != NULL) {
return len;
}
// unknown response, but we've attempted send
printf("esp8266_write: post-send resp: %s\r\n", buf);
return len;
}
// ESP8266 读取数据,返回读取的字节数
uint16_t esp8266_read(char *data, uint16_t buf_size)
{
// accumulate reads and search for +IPD, length:data pattern
char tmp[128];
char acc[512];
int acc_len = 0;
int total_timeout = 5000; // total wait up to 5s
int step = 200; // per-read timeout
acc[0] = '\0';
while (total_timeout > 0 && acc_len < (int)sizeof(acc) - 1)
{
int r = esp8266_read_response(tmp, sizeof(tmp), step);
if (r > 0)
{
// append
int copy = r < (int)sizeof(acc) - 1 - acc_len ? r : (int)sizeof(acc) - 1 - acc_len;
memcpy(acc + acc_len, tmp, copy);
acc_len += copy;
acc[acc_len] = '\0';
// debug
printf("esp8266_acc: %s\r\n", acc);
// search for +IPD,
char *pfind = strstr(acc, "+IPD,");
if (pfind)
{
pfind += 5; // move past +IPD,
// parse number until ':'
int len = 0;
while (*pfind && *pfind != ':' && len < 100000)
{
if (*pfind >= '0' && *pfind <= '9')
len = len * 10 + (*pfind - '0');
pfind++;
}
if (*pfind == ':')
{
pfind++; // data start
int copylen = len < (int)buf_size - 1 ? len : (int)buf_size - 1;
// ensure we have enough bytes in acc; if not, try to read more briefly
int available = (int)(acc + acc_len - pfind);
if (available < copylen)
{
// try one more short read
int r2 = esp8266_read_response(tmp, sizeof(tmp), 500);
if (r2 > 0)
{
int c = r2 < (int)sizeof(acc) - 1 - acc_len ? r2 : (int)sizeof(acc) - 1 - acc_len;
memcpy(acc + acc_len, tmp, c);
acc_len += c;
acc[acc_len] = '\0';
}
}
// copy payload
memcpy(data, pfind, copylen);
data[copylen] = '\0';
return (uint16_t)copylen;
}
}
}
else
{
total_timeout -= step;
}
}
return 0;
}
// ESP8266 清空读缓冲区
void esp8266_clear_read_buf(void)
{
queue_clear(&usart2_rx_queue);
}
+36
View File
@@ -0,0 +1,36 @@
#ifndef __ESP8266_H
#define __ESP8266_H
#include <stm32f10x_conf.h>
// ESP8266初始化
void esp8266_init(void);
// ESP8266通过USART2发送字符串数据
void esp8266_send_string(const char *buf);
// ESP8266通过USART2发送AT指令
void esp8266_send_cmd(const char *cmd);
// 从USART2 读取相应字符串放入 buf,等待最大时长timeout毫秒ms
int esp8266_read_response(char *buf, int buf_size, int timeout_ms);
// ESP8266 连接 Wifi,成功返回1,失败返回0
int esp8266_connect_wifi(const char *ssid, const char *passwd);
// ESP8266 作为客户端远程 TCP 连接。成功返回1,失败返回0
int esp8266_tcp_connect(const char *ip, uint16_t port);
// 关闭tcp 连接
void esp8266_tcp_close(void);
// ESP8266 TCP 协议发送数据,返回写入的字节数,0表示失败
int esp8266_write(const char *data, uint16_t len);
// ESP8266 读取数据,返回读取的字节数
uint16_t esp8266_read(char *buf, uint16_t buf_size);
// ESP8266 清空读缓冲区
void esp8266_clear_read_buf(void);
#endif // __ESP8266_H
+162
View File
@@ -0,0 +1,162 @@
// #include "exti_button.h"
// #include "button.h"
// #include "led.h"
// /*
// * ---按键-----+--PIN--+---输入方式---+--CNF 位的值--+--MODE 位的值--+--按下状态--
// * KEY0 | PC9 | 上拉输入 | 10 | 00 | 0
// * KEY1 | PC8 | 上拉输入 | 10 | 00 | 0
// * KEY2(WK_UP) | PA0 | 下拉输入 | 10 | 00 | 1
// */
// /*
// * 外部终端实验,当 Key2 按下时,点亮或熄灭 LED2
// */
// // 初始化 Key2,将 Key2 设置成中断控制。
// void exti_button2_init(void)
// {
// NVIC_InitTypeDef NVIC_InitStruct;
// EXTI_InitTypeDef EXTI_InitStruct;
// // 开启按键的时钟,并初始化 PC8/PC9/PA0 的输入模式
// button_init();
// // 开启按键的复用 IO 时钟(使用中断必须开启复用时钟)
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
// // 开启并设置 NVIC
// // 设置 EXTI0 的设置
// NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn;
// // 抢占是优先级
// NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
// // 子优先级
// NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;
// NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
// NVIC_Init(&NVIC_InitStruct);
// // 开启并设置 EXTI
// // 配置 EXTI0 的中断线选择 PA0
// GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
// // EXTI 的第 0 号线
// EXTI_InitStruct.EXTI_Line = EXTI_Line0;
// // 中断还是事件,我们
// EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
// // 上升沿触发
// EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;
// // 使能
// EXTI_InitStruct.EXTI_LineCmd = ENABLE;
// //
// EXTI_Init(&EXTI_InitStruct);
// }
// // EXTI0 的中断处理函数
// void EXTI0_IRQHandler(void)
// {
// if (EXTI_GetITStatus(EXTI_Line0) == SET)
// {
// // 清除中断挂起屏蔽位
// EXTI_ClearITPendingBit(EXTI_Line0);
// led_set_status(2, !led_get_status(2));
// }
// }
#include "exti_button.h"
#include "button.h"
#include "led.h"
#include "beep.h"
/*
* ---按键-----+--PIN--+---输入方式---+--CNF 位的值--+--MODE 位的值--+--按下状态--
* KEY0 | PC9 | 上拉输入 | 10 | 00 | 0
* KEY1 | PC8 | 上拉输入 | 10 | 00 | 0
* KEY2(WK_UP) | PA0 | 下拉输入 | 10 | 00 | 1
*/
/*
* 外部终端实验,当 Key0 按下时,点亮或熄灭 LED0
*/
// 初始化 Key0,将 Key0 设置成中断控制。
void exti_button0_init(void) // 函数名可以改一下,更清晰
{
NVIC_InitTypeDef NVIC_InitStruct;
EXTI_InitTypeDef EXTI_InitStruct;
// 开启按键的时钟,并初始化 PC8/PC9/PA0 的输入模式
button_init();
// 开启复用 IO 时钟(使用中断必须开启复用时钟)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
// --- 1. 修改 NVIC 配置 ---
// 设置 EXTI9_5 的中断通道
NVIC_InitStruct.NVIC_IRQChannel = EXTI9_5_IRQn; // 从 EXTI0_IRQn 修改为 EXTI9_5_IRQn
// 抢占优先级
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
// 子优先级
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1; // 子优先级也可以调整
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
// --- 2. 修改 EXTI 配置 ---
// 配置 EXTI9 的中断线选择 PC9
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource9); // 从 GPIOA, PinSource0 修改
// EXTI 的第 9 号线
EXTI_InitStruct.EXTI_Line = EXTI_Line9; // 从 EXTI_Line0 修改为 EXTI_Line9
// 模式:中断
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
// KEY0 是上拉输入,按下变低电平,所以是下降沿触发
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;
// 使能
EXTI_InitStruct.EXTI_LineCmd = ENABLE;
// 初始化
EXTI_Init(&EXTI_InitStruct);
}
// --- 3. 修改中断服务函数 ---
// EXTI9_5 的中断处理函数 (处理 EXTI 线 5 到 9)
// void EXTI9_5_IRQHandler(void)
// {
// // 检查是否是 EXTI Line9 触发的中断
// if (EXTI_GetITStatus(EXTI_Line9) == SET)
// {
// // 清除 Line9 上的中断挂起屏蔽位
// EXTI_ClearITPendingBit(EXTI_Line9);
// // --- 4. 修改控制的 LED ---
// // 翻转 LED0 的状态
// led_set_status(1, !led_get_status(1));
// }
// // 如果你还用了 EXTI5, 6, 7, 8,可以在这里继续添加 if 判断
// }
void EXTI9_5_IRQHandler(void)
{
// 检查是否是 EXTI Line9 触发的中断
if (EXTI_GetITStatus(EXTI_Line9) == SET)
{
// 清除 Line9 上的中断挂起屏蔽位
EXTI_ClearITPendingBit(EXTI_Line9);
// --- 核心修改部分:翻转蜂鸣器的状态 ---
// 1. 读取蜂鸣器引脚(PC7)当前的输出状态
// GPIO_ReadOutputDataBit返回0或1
if (GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_7) == 1)
{
// 如果当前是响的 (高电平), 就关闭它
beep_off();
}
else
{
// 如果当前是关的 (低电平), 就打开它
beep_on();
}
}
}
+11
View File
@@ -0,0 +1,11 @@
#ifndef __EXTI_BUTTON_H
#define __EXTI_BUTTON_H
#include <stm32f10x_conf.h>
// 初始化 Key2,将 Key2 设置成中断控制。
void exti_button2_init(void);
#endif // EXTI_BUTTON_H
+157
View File
@@ -0,0 +1,157 @@
#include "systick.h"
#include "bitband.h"
#include "gpio_iic.h"
static GPIO_InitTypeDef GPIO_InitStructSDAOut;
static GPIO_InitTypeDef GPIO_InitStructSDAIn;
// 位段定义
#define IIC_SCL_OUT PBOut(6)
#define IIC_SDA_OUT PBOut(7)
#define IIC_SDA_IN PBIn(7)
// 初始化 IIC 的IO 端口:SDA:PB7,SCL:PB6
void iic_init(void)
{
GPIO_InitTypeDef GPIO_InitStructSCL;
// 使能时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
// 初始化 PB6 为开漏输出
GPIO_InitStructSCL.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStructSCL.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructSCL.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructSCL);
// 初始化 PB7 为开漏输出
GPIO_InitStructSDAOut.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStructSDAOut.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructSDAOut.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructSDAOut);
// 设置 SCL和SDA 都为高电平
IIC_SCL_OUT = 1;
IIC_SDA_OUT = 1;
// 填充 PB7 为上拉输入状态的结构体(后续备用)
GPIO_InitStructSDAIn.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructSDAIn.GPIO_Pin = GPIO_Pin_7;
}
// 设置 SDA 为输入模式
static void iic_set_sda_in(void)
{
GPIO_Init(GPIOB, &GPIO_InitStructSDAIn);
}
// 设置 SDA 为输出模式
static void iic_set_sda_out(void)
{
GPIO_Init(GPIOB, &GPIO_InitStructSDAOut);
}
// 主机发送起始信号
void iic_start(void)
{
iic_set_sda_out();
IIC_SDA_OUT = 1;
IIC_SCL_OUT = 1;
delay_us(2);
IIC_SDA_OUT = 0;
delay_us(2);
IIC_SCL_OUT = 0;
delay_us(1);
}
//主机发送停止信号
void iic_stop(void)
{
iic_set_sda_out();
IIC_SCL_OUT = 0;
IIC_SDA_OUT = 0;
delay_us(2);
IIC_SCL_OUT = 1;
delay_us(1);
IIC_SDA_OUT = 1;
delay_us(2);
}
// 主机发送一个字节
void iic_send_byte(u8 txd)
{
int bit;
iic_set_sda_out();
for (bit = 7; bit >= 0; bit--) {
// 拉低时钟线
IIC_SCL_OUT = 0;
delay_us(1);
// 变化数据线的数据
IIC_SDA_OUT = (txd >> bit) & 0x01;
delay_us(1);
IIC_SCL_OUT = 1;
delay_us(2);
}
IIC_SCL_OUT = 0; // 发送完毕拉低时钟线。
}
// 主机接收一个字节并回复ack,参数ack:1表示应答,0表示非应答。
u8 iic_recv_byte(u8 ack)
{
int bit;
u8 value = 0; // 用于保存最终的返回值
iic_set_sda_in(); // 设置为输入模式
for (bit = 7; bit >= 0; bit--) {
IIC_SCL_OUT = 0; // 拉低时钟线
delay_us(2);
IIC_SCL_OUT = 1;
delay_us(2);
if (IIC_SDA_IN) {
value |= (0x01 << bit);
}
}
IIC_SCL_OUT = 0;
// 接收8为数据,根据参数ack 回复应答或非应答。
if (ack)
iic_send_ack();
else
iic_send_nack();
return value;
}
// 主机等待从机,如果从机未响应(收到NACK),则发送停止
// 信号结束本次通信,非应答返回1(NACK),应答返回0,ACK);
u8 iic_wait_ack(void)
{
u8 error_timeout = 0;
IIC_SCL_OUT = 0; // 拉低时钟线
iic_set_sda_in(); // 设置为输入模式
delay_us(1);
IIC_SCL_OUT = 1; // 拉高时钟线。
// 等待从机拉低的引号
while (IIC_SDA_IN) {
error_timeout++;
if (error_timeout > 250) {
iic_stop(); // 发送停止信号,然后返回1
return 1;
}
}
IIC_SCL_OUT = 0; // 拉低时钟线
return 0;
}
// 主机发送 ACK
void iic_send_ack(void)
{
IIC_SCL_OUT = 0; // 拉低时钟线
iic_set_sda_out(); // 变为输出模式
IIC_SDA_OUT = 0; // 低电平为应答ACK
delay_us(2);
IIC_SCL_OUT = 1; // 拉高时钟线
delay_us(2);
IIC_SCL_OUT = 0;
}
// 主机发送 NACK
void iic_send_nack(void)
{
IIC_SCL_OUT = 0; // 拉低时钟线
iic_set_sda_out(); // 变为输出模式
IIC_SDA_OUT = 1; // 高电平为非应答NACK
delay_us(2);
IIC_SCL_OUT = 1; // 拉高时钟线
delay_us(2);
IIC_SCL_OUT = 0;
}
+26
View File
@@ -0,0 +1,26 @@
#ifndef __GPIO_IIC_H
#define __GPIO_IIC_H
#include <stm32f10x_conf.h>
typedef unsigned char u8;
// 初始化 IIC 的IO 端口:SDA:PB7,SCL:PB6
void iic_init(void);
// 主机发送起始信号
void iic_start(void);
//主机发送停止信号
void iic_stop(void);
// 主机发送一个字节
void iic_send_byte(u8 txd);
// 主机接收一个字节并回复ack,参数ack:1表示应答,0表示非应答。
u8 iic_recv_byte(u8 ack);
// 主机等待从机,如果从机未响应(收到NACK),则发送停止
// 信号结束本次通信,非应答返回1(NACK),应答返回0,ACK);
u8 iic_wait_ack(void);
// 主机发送 ACK
void iic_send_ack(void);
// 主机发送 NACK
void iic_send_nack(void);
#endif // __GPIO_IIC_H
+25
View File
@@ -0,0 +1,25 @@
#include "iwdg.h"
// 独立看门狗初始化,参数为重置的时长 ms
void iwdg_init(int ms)
{
// 开启看门狗,向键寄存器写入 0x5555
IWDG->KR = 0x5555;
// 设置预分频器为 64 分频
IWDG->PR = IWDG_Prescaler_64;
// 设置重加载值 ms
IWDG->RLR = 40000 / 64 * ms / 1000;
// 让看门狗重加载计数值
IWDG->KR = 0xAAAA;
// 启动看门狗计数
IWDG->KR = 0xCCCC;
}
// 喂狗函数
void iwdg_feed_dog(void)
{
// 让看门狗重加载计数值
IWDG->KR = 0xAAAA;
}
+12
View File
@@ -0,0 +1,12 @@
#ifndef __IWDG_H
#define __IWDG_H
#include <stm32f10x_conf.h>
// 独立看门狗初始化,参数为重置的时长 ms
void iwdg_init(int ms);
// 喂狗函数
void iwdg_feed_dog(void);
#endif // __IWDG_H
+90
View File
@@ -0,0 +1,90 @@
#include "led.h"
// 初始化 LED
void led_init()
{
// 定义一个 GPIO 初始化啊的结构体
GPIO_InitTypeDef GPIO_InitStruct;
// 初始化时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOA, ENABLE);
// 将 PC8 和 PC9 设置成上拉输入 1000
// up 上拉
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
// 针脚
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
// 输出速度
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStruct);
}
// 让编号为 nu 的 LED 点亮, nu 为0,1,2 代表 LED0, LED1,LED2
void led_on(int nu)
{
switch (nu)
{
case 0:
GPIOc->ODR |= (0x1 << 1);
break;
case 1:
GPIOc->ODR |= (0x1 << 2);
break;
case 2:
GPIOc->ODR |= (0x1 << 3);
break;
default:
break;
}
}
// 让编号为 nu 的 LED 熄灭
void led_off(int nu)
{
switch (nu)
{
case 0:
GPIOc->ODR &= ~(0x1 << 1);
break;
case 1:
GPIOc->ODR &= ~(0x1 << 2);
break;
case 2:
GPIOc->ODR &= ~(0x1 << 3);
break;
default:
break;
}
}
// 获取编号为 nu 的 LED 的状态值
int led_get_status(int nu)
{
uint32_t ret;
if (nu >= 0 && nu <= 2)
{
ret = GPIOc->ODR & (0x1 << (1 + nu));
return ret != 0 ? 1:0;
}
return 0;
}
// 设置编号为 nu 的 LED 的状态值 status, 0:熄灭, 1:点亮
void led_set_status(int nu, int status)
{
if (status)
{
led_on(nu);
} else {
led_off(nu);
}
}
+44
View File
@@ -0,0 +1,44 @@
#ifndef __LED_H
#define __LED_H
#include <stm32f10x_conf.h>
// #define GPIOC_CRL *(volatile unsigned int *)(0x40011000 + 0x00)
// #define GPIOC_ODR *(volatile unsigned int *)(0x40011000 + 0x0C)
// 定义一个无符号类型的 4 字节整数的别名 uint32_t
typedef unsigned int uint32_t;
// 定义一个无符号类型的 2 字节整数的别名 uint16_t
typedef unsigned short int uint16_t;
typedef struct
{
uint32_t CRL; // offset 0x00
uint32_t CRH; // offset 0x04
uint32_t IDR; // offset 0x08
uint32_t ODR; // offset 0x0c
uint32_t BSRR; // offset 0x10
uint32_t BRR; // offset 0x14
uint32_t LCKR; // offset 0x18
} GPIO_typedef;
// 定义 GPIOC 的基地址是 0x40011000
#define GPIOC_base (0x40011000)
// 定义一个 GPIO_typedef 类型指针 GPIOc 指向 0x40011000
#define GPIOc ((GPIO_typedef *)GPIOC_base)
// 初始化 LED
void led_init(void);
// 让编号为 nu 的 LED 点亮, nu 为0,1,2 代表 LED0, LED1,LED2
void led_on(int nu);
// 让编号为 nu 的 LED 熄灭
void led_off(int nu);
// 获取编号为 nu 的 LED 的状态值
int led_get_status(int nu);
// 设置编号为 nu 的 LED 的状态值 status, 0:熄灭, 1:点亮
void led_set_status(int nu, int status);
#endif // __LED_H
+192
View File
@@ -0,0 +1,192 @@
#include "led_digital_tube.h"
#include "bitband.h"
#include "systick.h"
// 显示文字内容表
static u8 table[] = {
0x3f,0x06,0x5b,0x4f, // 0 1 2 3
0x66,0x6d,0x7d,0x07, // 4 5 6 7
0x7f,0x6f,0x77,0x7c, // 8 9 A b
0x39,0x5e,0x79,0x71 // C d E F
};
// HC138 管脚位段定义
#define HC138_A0 PCOut(11)
#define HC138_A1 PCOut(12)
#define HC138_A2 PCOut(2)
// HC595 管脚位段定义
#define HC595_DATA PBOut(3) // 接 DS 管脚
#define HC595_LCLK PBOut(4) // 接 ST_CP 管脚
#define HC595_SCLK PBOut(5) // 接 SH_CP 管脚
// 初始化数码管
void led_digital_tube_init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
// 开启 GPIO 相关的时钟
RCC_APB2PeriphClockCmd(
RCC_APB2Periph_GPIOB |
RCC_APB2Periph_GPIOC |
RCC_APB2Periph_GPIOD |
RCC_APB2Periph_AFIO,
ENABLE);
// 保留 SWD 调试能力的前提下
// 将 PB3/PB4/PA15 这三个管脚从 JTAG 功能中释放出来
// 作为普通 GPIO 使用,从而有效的增加项目可用 I/O 数量
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
// 使能 HC138 芯片管脚 (PC11/PC12/PD2)
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2;
GPIO_Init(GPIOD, &GPIO_InitStruct);
// 初始化 HC595 芯片使用的管脚(PB3/PB4/PB5)
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;
GPIO_Init(GPIOB, &GPIO_InitStruct);
}
// hc138 设置地址
void hc138_out_data(u8 data)
{
switch (data)
{
case 0:
HC138_A2 = 0;
HC138_A1 = 0;
HC138_A0 = 0;
break;
case 1:
HC138_A2 = 0;
HC138_A1 = 0;
HC138_A0 = 1;
break;
case 2:
HC138_A2 = 0;
HC138_A1 = 1;
HC138_A0 = 0;
break;
case 3:
HC138_A2 = 0;
HC138_A1 = 1;
HC138_A0 = 1;
break;
default:
break;
}
}
// hc595 发送数据
void hc595_send_data(u8 data)
{
// 循环变量
uint8_t i =0;
// 高位先发送,SH_CP 位低电平时变化数据
// SH_CP 的上升沿会将 DS 数据放入移位寄存器并移位
for (i = 0; i < 8; i++)
{
// SH_CP 管脚拉低并准备发送数据
HC595_SCLK = 0;
// 根据数据的最高位来变化 DS 数据线
if (data & 0x80)
{
HC595_DATA = 1;
} else {
HC595_DATA = 0;
}
// 左移 1位,丢掉最高位
data <<= 1;
// 上升沿锁定一个位到移位寄存器
HC595_SCLK = 1;
}
// 8 个数据位发送结束,将 HC595 从低到高(制造一个上升沿)
HC595_LCLK = 0;
// delay_ms(1);
// 上升沿
HC595_LCLK = 1;
}
// 数码管显示 4 位整数(低四位)
void led_digital_show_interger(int data)
{
uint8_t buf[4] ={0};
uint8_t i = 0;
// 计算千位
buf[0] = data / 1000 % 10;
// 计算百位
buf[1] = data / 100 % 10;
// 计算十位
buf[2] = data / 10 % 10;
// 计算个位
buf[3] = data / 1 % 10;
// 循环显示 4 位数据
for ( i = 0; i < 4; i++)
{
// 设置哪个晶体管亮(0时最左侧亮)
hc138_out_data(i);
// 显示数字
hc595_send_data(table[buf[i]]);
// hc595_send_data(0xFF);
// 停留 1ms
delay_ms(1);
// 熄灭
hc595_send_data(0);
}
}
// 数码管显示 4 位小数(ndigit 表示小数点后保留有数位数 0~3 位)
void led_digital_show_float(float value, int ndigit/* 小数位数 0~3 */)
{
uint8_t buf[4] ={0};
uint8_t i = 0;
float temp = value;
int data;
// 如果小数点位数不在合法范围内
// 则让小数点放在最右边(小数部分位 0 位)
if (ndigit > 3 || ndigit < 0)
{
ndigit = 0;
}
// 将 temp 扩大 10的 ndigit 次方倍
for (i = 0; i < ndigit; i++)
{
temp *= 10;
}
data = temp;
buf[0] = data / 1000 % 10;
buf[1] = data / 100 % 10;
buf[2] = data / 10 % 10;
buf[3] = data / 1 % 10;
// 循环显示 4 位数据
for ( i = 0; i < 4; i++)
{
// 设置哪个晶体管亮(0时最左侧亮)
hc138_out_data(i);
// 显示数字
hc595_send_data(table[buf[i]] | (i == 3 - ndigit ? 0x80 : 0x00));
// hc595_send_data(0xFF);
// 停留 1ms
delay_ms(1);
// 熄灭
hc595_send_data(0);
}
}
+41
View File
@@ -0,0 +1,41 @@
#ifndef __LED_DIGITAL_TUBE_H
#define __LED_DIGITAL_TUBE_H
/*
* 74HC138 译码器
* 地址输入三条,输出 八根线
* 输入:
* HC138 A0 ---> PC11
* HC138 A1 ---> PC12
* HC138 A2 ---> PD2
* 输出:
* Y0 --> CH1
* Y1 --> CH2
* Y2 --> CH3
* Y3 --> CH4
* Y4~Y7 --> CH1
*
* 74HC595
* 输入:
* 时钟输入: HC595 SCLK11(SH_CP) --> PB5
* 时钟输入: HC595 LCLK12(ST_CP) --> PB4(JNTRST)
* 数据输入: HC595 DATA(DS) --> PB3(PB3/JTDO/TRACESWO)
* 输出:
* QA-QH(共八根线)
*
*/
#include <stm32f10x_conf.h>
// 初始化数码管
void led_digital_tube_init(void);
// hc138 设置地址
void hc138_out_data(u8 data);
// hc595 发送数据
void hc595_send_data(u8 data);
// 数码管显示 4 位整数(低四位)
void led_digital_show_interger(int data);
// 数码管显示 4 位小数(ndigit 表示小数点后保留有数位数 0~3 位)
void led_digital_show_float(float value, int ndigit/* 小数位数 0~3 */);
#endif // __LED_DIGITAL_TUBE_H
+329
View File
@@ -0,0 +1,329 @@
// 作者:魏明择
#include "oled.h"
#include "stdlib.h"
#include "systick.h"
#include "gpio_iic.h"
#include "wfont.h"
#include "string.h"
uint8_t OLED_frame_buffer[128][8] = {0};
void iic_start_Oled(void)
{
iic_start();
}
void iic_stop_Oled(void)
{
iic_stop();
}
void iic_wait_ack_Oled(void)
{
iic_wait_ack();
}
void OLED_write_command(u8 IIC_Command)
{
iic_start();
iic_send_byte(0x78);
iic_wait_ack();
iic_send_byte(0x00);
iic_wait_ack();
iic_send_byte(IIC_Command);
iic_wait_ack();
iic_stop();
}
void OLED_write_data(u8 IIC_Data)
{
iic_start();
iic_send_byte(0x78);
iic_wait_ack();
iic_send_byte(0x40);
iic_wait_ack();
iic_send_byte(IIC_Data);
iic_wait_ack();
iic_stop();
}
void oled_fill(u8 fill_Data)
{
u8 page;
u8 n;
for (page = 0; page < 8; page++)
for (n = 0; n < 128; n++)
OLED_frame_buffer[n][page] = fill_Data;
}
void oled_draw_picture(const u8 *buf)
{
const u8 *p = buf;
int page;
int x;
for (page = 0; page < 8; page++)
{
for (x = 0; x < 128; x++)
{
OLED_frame_buffer[x][page] = *p;
p++;
}
}
}
void oled_display_on(void)
{
OLED_write_command(0X8D);
OLED_write_command(0X14);
OLED_write_command(0XAF);
}
void oled_display_off(void)
{
OLED_write_command(0X8D);
OLED_write_command(0X10);
OLED_write_command(0XAE);
}
void oled_clear_frame_buffer(void)
{
memset(OLED_frame_buffer, 0, sizeof(OLED_frame_buffer));
}
void oled_clear(void)
{
oled_clear_frame_buffer();
oled_refresh_framebuffer();
}
void oled_init(void)
{
iic_init();
delay_ms(800);
OLED_write_command(0xAE); // display off
OLED_write_command(0x20); // Set Memory Addressing Mode
OLED_write_command(0x10); // 00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid
OLED_write_command(0xb0); // Set Page Start Address for Page Addressing Mode,0-7
OLED_write_command(0xc8); // Set COM Output Scan Direction
OLED_write_command(0x02); //---set low column address
OLED_write_command(0x10); //---set high column address
OLED_write_command(0x40); //--set start line address
OLED_write_command(0x81); //--set contrast control register
OLED_write_command(0xCf); // 7f
OLED_write_command(0xa1); //--set segment re-map 0 to 127
OLED_write_command(0xa6); //--set normal display
OLED_write_command(0xa8); //--set multiplex ratio(1 to 64)
OLED_write_command(0x3F); //
OLED_write_command(0xa4); // 0xa4,Output follows RAM content;0xa5,Output ignores RAM content
OLED_write_command(0xd3); //-set display offset
OLED_write_command(0x00); //-not offset
OLED_write_command(0xd5); //--set display clock divide ratio/oscillator frequency
OLED_write_command(0xf0); //--set divide ratio
OLED_write_command(0xd9); //--set pre-charge period
OLED_write_command(0x22); //
OLED_write_command(0xda); //--set com pins hardware configuration
OLED_write_command(0x12);
OLED_write_command(0xdb); //--set vcomh
OLED_write_command(0x40); // 0x20,0.77xVcc
OLED_write_command(0x8d); //--set DC-DC enable
OLED_write_command(0x14); //
OLED_write_command(0xaf); //--turn on oled panel
/*
OLED_write_command(0xAE);//--display off
OLED_write_command(0x00);//---set low column address
OLED_write_command(0x10);//---set high column address
OLED_write_command(0x40);//--set start line address
OLED_write_command(0xB0);//--set page address
OLED_write_command(0x81); // contract control
OLED_write_command(0xFF);//--128
OLED_write_command(0xA1);//set segment remap
OLED_write_command(0xA6);//--normal / reverse
OLED_write_command(0xA8);//--set multiplex ratio(1 to 64)
OLED_write_command(0x3F);//--1/32 duty
OLED_write_command(0xC8);//Com scan direction
OLED_write_command(0xD3);//-set display offset
OLED_write_command(0x00);//
OLED_write_command(0xD5);//set osc division
OLED_write_command(0x80);//
OLED_write_command(0xD8);//set area color mode off
OLED_write_command(0x05);//
OLED_write_command(0xD9);//Set Pre-Charge Period
OLED_write_command(0xF1);//
OLED_write_command(0xDA);//set com pin configuartion
OLED_write_command(0x12);//
OLED_write_command(0xDB);//set Vcomh
OLED_write_command(0x30);//
OLED_write_command(0x8D);//set charge pump enable
OLED_write_command(0x14);//
OLED_write_command(0xAF);//--turn on oled panel
*/
}
void oled_draw_point(u8 x, u8 y, u8 val)
{
u8 page;
u8 row;
u8 point_pos = 0;
if (x > 127 || y > 63)
return; // 超出范围
page = y >> 3;
row = y & 0x7;
point_pos = 1 << row; // 计算点在页的相对位置
if (val)
OLED_frame_buffer[x][page] |= point_pos; // 写1
else
OLED_frame_buffer[x][page] &= ~point_pos; // 写0
}
// 更新显示的点到OLED
void oled_refresh_framebuffer(void)
{
u8 page;
u8 x;
for (page = 0; page < 8; page++)
{
OLED_write_command(0xB0 + page); // 设置页地址(0~7)
OLED_write_command(0x00); // 设置显示位置—列低地址
OLED_write_command(0x10); // 设置显示位置—列高地址
for (x = 0; x < 128; x++)
OLED_write_data(OLED_frame_buffer[x][page]);
} // 更新显示
}
void oled_draw_chinese_text16(u8 x, u8 y, int cn_index)
{
int i, j;
int page = y >> 3;
cn_index <<= 1;
for (i = 0; i < 16; i++)
{
for (j = 0; j < 2; j++)
{
OLED_frame_buffer[x + i][page + j] = hanzi16x16[cn_index + j][i];
}
}
}
void OLED_draw_english_text8(u8 x, u8 y, int en_index)
{
int i;
int page = y >> 3;
for (i = 0; i < 6; i++)
{
OLED_frame_buffer[x + i][page] = ascii6x8[en_index * 6 + i];
}
}
void oled_draw_text8(u8 x, u8 y, const char *text)
{
const char *p = text;
while (*p && x < 128 && y < 64)
{
if ((*p) & 0x80)
{ // 中文跳过
p += 2;
x += 12;
}
else
{ // 英文
OLED_draw_english_text8(x, y, *p - ' ');
p++;
x += 6;
}
}
}
void OLED_draw_english_text16(u8 x, u8 y, int en_index)
{
int i;
int j;
int page = y >> 3;
for (i = 0; i < 8; i++)
{
for (j = 0; j < 2; j++)
{
OLED_frame_buffer[x + i][page + j] = ascii8x16[(en_index << 4) + (j << 3) + i];
}
}
}
void oled_draw_text16(u8 x, u8 y, const char *text)
{
const char *p = text;
while (*p && x < 128 && y < 64)
{
if ((*p) & 0x80)
{ // 中文
// 查找中文是第几个汉字
const char *p_cn = hanzi_utf8_index;
int cn_index = 0;
while (*p_cn)
{
if (strncmp(p_cn, p, 2) == 0)
{
oled_draw_chinese_text16(x, y, cn_index);
break;
}
p_cn += 2;
cn_index++;
}
p += 2;
x += 16;
}
else
{ // 英文
OLED_draw_english_text16(x, y, *p - ' ');
p++;
x += 8;
}
}
}
void oled_draw_rect(u8 x0, u8 y0, u8 x1, u8 y1)
{
u8 x;
u8 y;
for (x = x0; x <= x1; x++)
{
oled_draw_point(x, y0, 1);
oled_draw_point(x, y1, 1);
}
for (y = y0 + 1; y < y1; y++)
{
oled_draw_point(x0, y, 1);
oled_draw_point(x1, y, 1);
}
}
void oled_fill_rect(u8 x0, u8 y0, u8 x1, u8 y1)
{
u8 x;
u8 y;
for (x = x0; x <= x1; x++)
for (y = y0; y <= y1; y++)
oled_draw_point(x, y, 1);
}
void oled_fill_circle(u8 x, u8 y, u8 r) // 画一个点
{
u8 i = 0;
u8 j = 0;
for (j = y - r; j <= y + r; j++)
for (i = x - r; i <= x + r; i++)
if ((x - i) * (x - i) + (y - j) * (y - j) <= r * r)
oled_draw_point(i, j, 1);
}
+55
View File
@@ -0,0 +1,55 @@
#ifndef __OLED_H
#define __OLED_H
#include "stdlib.h"
typedef unsigned char u8;
typedef unsigned int u32;
// 打开显示屏
void oled_display_on(void);
// 关闭显示屏(省电)
void oled_display_off(void);
// 初始化 OLED
void oled_init(void);
// 清空屏幕
void oled_clear_frame_buffer(void);
void oled_clear(void);
// 绘制点
void oled_draw_point(u8 x, u8 y, u8 val);
// 绘制矩形
void oled_draw_rect(u8 x0, u8 y0, u8 x1, u8 y1);
// 绘制填充矩形
void oled_fill_rect(u8 x0, u8 y0, u8 x1, u8 y1);
// 绘制填充圆形
void oled_fill_circle(u8 x, u8 y, u8 r);
// 使用某个值填充屏幕
void oled_fill(u8 fill_Data);
// 在屏幕绘制图片
void oled_draw_picture(const u8 * buf);
// 将FrameBuffer复制到屏幕上
void oled_refresh_framebuffer(void);
// 写6x8的英文
void oled_draw_text8(u8 x, u8 y, const char *text);
// 写8x16的英文或8x16的中文
void oled_draw_text16(u8 x, u8 y, const char *text);
#endif
+45
View File
@@ -0,0 +1,45 @@
#include "queue.h"
// 1. 初始化队列
void queue_init(struct queue *pq)
{
pq->tail = pq->head = 0;
}
// 2. 队列空判断, 空返回1, 否则返回0
int queue_is_empty(struct queue *pq)
{
return pq->head == pq->tail;
}
// 3. 队列满判断, 满返回1, 否则返回0
int queue_is_full(struct queue *pq)
{
int tail_next = (pq->tail + 1) % QUEUE_DATA_SIZE;
if (tail_next == pq->head)
return 1;
return 0;
}
// 4. 入队, 成功返回1 ,失败返回0
int queue_enqueue(struct queue *pq, int value)
{
if (queue_is_full(pq))
return 0;
pq->data[pq->tail] = value;
pq->tail = (pq->tail + 1) % QUEUE_DATA_SIZE;
return 1;
}
// 5. 出队, 成功返回1 ,失败返回0
int queue_dequeue(struct queue *pq, int *pvalue)
{
if (queue_is_empty(pq))
return 0;
*pvalue = pq->data[pq->head];
pq->head = (pq->head + 1) % QUEUE_DATA_SIZE;
return 1;
}
// 7. 清空队列
void queue_clear(struct queue *pq)
{
pq->head = pq->tail = 0;
}
+29
View File
@@ -0,0 +1,29 @@
#ifndef __QUEUE_H
#define __QUEUE_H
#define QUEUE_DATA_SIZE (64) // 定义队列内存储空间
struct queue
{
char data[QUEUE_DATA_SIZE]; // 用来保存数据
unsigned short int head; // 队列头位置索引。
unsigned short int tail; // 队列尾位置索引。
};
// 1. 初始化队列
void queue_init(struct queue *pq);
// 2. 队列空判断, 空返回1, 否则返回0
int queue_is_empty(struct queue *pq);
// 3. 队列满判断, 满返回1, 否则返回0
int queue_is_full(struct queue *pq);
// 4. 入队, 成功返回1 ,失败返回0
int queue_enqueue(struct queue *pq, int value);
// 5. 出队, 成功返回1 ,失败返回0
int queue_dequeue(struct queue *pq, int *pvalue);
// 7. 清空队列
void queue_clear(struct queue *pq);
#endif // _QUEUE_H
+68
View File
@@ -0,0 +1,68 @@
#include "systick.h"
// 用于记住每一微妙的时钟计数
volatile static u8 fac_us = 0;
// 用于记住每一毫秒妙的时钟计数
volatile static u16 fac_ms = 0;
// 初始化 systick
void systick_init(void)
{
// 初始化 SysTick 的时钟为外部时钟
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
fac_us = SYSCLK / 8;
fac_ms = SYSCLK / 8 * 1000;
}
// 延时 us 微秒
void delay_us(u32 us)
{
// 用于保存寄存器状态
u32 temp;
// 设置重加载值
SysTick->LOAD = us * fac_us;
// 清空当前值
SysTick->VAL = 0;
// 使能 SysTick
SysTick->CTRL |= 0x1;
// 循环等待定时器到时
do
{
temp = SysTick->CTRL;
} while (!(temp & (1 << 16)) && (temp & 0x1));
// 关闭 SysTick 定时器
SysTick->CTRL &= ~0x01;
// 当前计数清零
SysTick->VAL = 0;
}
// 延时 ms 毫秒
void delay_ms(u32 ms)
{
// 用于保存寄存器状态
u32 temp;
// 设置重加载值
SysTick->LOAD = ms * fac_ms;
// 清空当前值
SysTick->VAL = 0;
// 使能 SysTick
SysTick->CTRL |= 0x1;
// 循环等待定时器到时
do
{
temp = SysTick->CTRL;
} while (!(temp & (1 << 16)) && (temp & 0x1));
// 关闭 SysTick 定时器
SysTick->CTRL &= ~0x01;
// 当前计数清零
SysTick->VAL = 0;
}
// 延时 second 秒
void delay_s(u32 second)
{
while (second--)
{
delay_ms(1000);
}
}
+19
View File
@@ -0,0 +1,19 @@
#ifndef __SYSTICK_H
#define __SYSTICK_H
#include <stm32f10x_conf.h>
#include <stm32f10x.h>
// 定义系统时钟位 72Mhz
#define SYSCLK (72)
// 初始化 systick
void systick_init(void);
// 延时 us 微秒
void delay_us(u32 us);
// 延时 ms 毫秒
void delay_ms(u32 ms);
// 延时 second 秒
void delay_s(u32 second);
#endif //__SYSTICK_H
+193
View File
@@ -0,0 +1,193 @@
#include "usart1.h"
static struct queue usart1_rx_queue;
/*
* IO 管脚
* 接收管脚 PA10 USART1_RX (悬空输入)
* 发送管脚 PA9 USART1_TX (复用推挽输出)
* 另外一个线 VSS(共地)
*/
// 初始化 usart1, baud 为波特率
void usart1_init(uint32_t baud)
{
GPIO_InitTypeDef GPIO_InitStruct;
USART_InitTypeDef USART_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
// 初始化接收队列
queue_init(&usart1_rx_queue);
// 使能 PA9 和 PA10 的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// 使能 USART1 外设时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
// 设置 PA9 为发送管脚
// 复用推挽输出
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// 设置 PA10 为接收管脚
// 悬空输入
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// 初始化 USART1 控制器
// 设置波特率
USART_InitStruct.USART_BaudRate = baud;
// 字长 8bit
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
// 停止位 1bit
USART_InitStruct.USART_StopBits = USART_StopBits_1;
// 校验位(无)
USART_InitStruct.USART_Parity = USART_Parity_No;
// 收发
USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
// 硬件流控制(无)
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Init(USART1, &USART_InitStruct);
// 使能串口 1
USART_Cmd(USART1, ENABLE);
// 初始化接受中断(暂不接收)
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
// 清除中断标志位
USART_ClearFlag(USART1, USART_FLAG_TC);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
// 中断通道
NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
// 开启接收寄存器非空中断
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
}
// 编写冲断处理函数
void USART1_IRQHandler(void)
{
uint8_t ch;
// 如果是接收寄存器非空中断,则读取数据
if (USART_GetFlagStatus(USART1, USART_IT_RXNE) != RESET)
{
ch = USART_ReceiveData(USART1);
// 将接收到的字符放入接收队列
// 如果队列已满会丢掉此字节
queue_enqueue(&usart1_rx_queue, ch);
}
}
// 用于串口发送一个字节的数据
void usart1_put_char(uint8_t ch)
{
// 发送数据
USART_SendData(USART1, ch);
// 等待发送数据完毕
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) != SET);
}
// 用于串口发送一段数据,遇到 '\0' 结束
void usart1_output(const char *buf)
{
const char *pchar;
for (pchar = buf; *pchar; ++pchar)
{
usart1_put_char((uint8_t)*pchar);
}
}
// 用于串口发送一段数据,遇到 '\0' 结束,末尾添加 '\r\n' 换行符结束
void usart1_output_aline(const char *buf)
{
usart1_output(buf);
usart1_output("\r\n");
}
// 从串口读取一行数据放入 buf, buf 的最大长度为 buf_len
int usart1_input(char *buf, int buf_len)
{
int i = 0;
int ch = '\0';
for (i = 0; i < buf_len - 1; i++)
{
if (queue_is_empty(&usart1_rx_queue))
{
delay_ms(1);
if (queue_is_empty(&usart1_rx_queue))
{
break;
}
}
queue_dequeue(&usart1_rx_queue, &ch);
buf[i] = ch;
}
buf[i] = '\0';
return i;
}
// 从串口读取一行数据放入 buf, 当遇到 '\r\n' 时结束读取,并添加尾零 '\0'
int usart1_input_aline(char *buf, int buf_len)
{
int i;
int ch = '\0';
for ( i = 0; i < buf_len; i++)
{
// 等待,直到有数据读取
while (queue_is_empty(&usart1_rx_queue))
{
delay_ms(1);
}
queue_dequeue(&usart1_rx_queue, &ch);
buf[i] = ch;
// 遇到换行符
if (ch == '\n')
{
buf[i] = '\0';
// 检查前一个字符是否是回车符
if (i >= 1 && buf[i - 1] == '\r')
{
i--;
buf[i] = '\0';
}
break;
}
}
return i;
}
// 清空串口的接收队列
void usart1_clear_rx_queue(void)
{
}
// 添加 fputc 函数,实现 printf 重定向
int fputc(int ch, FILE *f)
{
usart1_put_char(ch);
return ch;
}
// 添加 fgetc 函数,实现 scanf 重定向
int fgetc(FILE *f)
{
int ch = '\0';
while (queue_is_empty(&usart1_rx_queue))
{
delay_ms(1);
}
queue_dequeue(&usart1_rx_queue, &ch);
return ch;
}
+38
View File
@@ -0,0 +1,38 @@
#ifndef __USART1_H
#define __USART1_H
/*
* IO 管脚
* 接受管脚 PA10 USART1_RX
* 发送管脚 PA9 USART1_TX
* 另外一个线 VSS(共地)
*/
#include <stdio.h>
#include "stm32f10x_conf.h"
#include "systick.h"
#include "queue.h"
// 初始化 usart1, baud 为波特率
void usart1_init(uint32_t baud);
// 用于串口发送一个字节的数据
void usart1_put_char(uint8_t ch);
// 用于串口发送一段数据,遇到 '\0' 结束
void usart1_output(const char *buf);
// 用于串口发送一段数据,遇到 '\0' 结束,末尾添加 '\r\n' 换行符结束
void usart1_output_aline(const char *buf);
// 从串口读取一行数据放入 buf, buf 的最大长度为 buf_len
int usart1_input(char *buf, int buf_len);
// 从串口读取一行数据放入 buf, 当遇到 '\r\n' 时结束读取,并添加尾零 '\0'
int usart1_input_aline(char *buf, int buf_len);
// 清空串口的接收队列
void usart1_clear_rx_queue(void);
#endif // __USART1_H
+285
View File
@@ -0,0 +1,285 @@
#include "wfont.h"
// 小象的图片
const unsigned char elephant128x64[]= {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0xC0,0x40,0x60,0x60,0x20,0x30,0x30,0x10,
0x10,0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x10,0x10,0x10,
0x10,0x30,0x30,0x20,0x20,0x60,0x40,0x40,0xC0,0x80,0x80,0x00,0x00,0x00,0x00,0x18,
0x1C,0x16,0x12,0x1B,0x1B,0x19,0x19,0x19,0x11,0x31,0x61,0x41,0xC1,0x83,0x03,0x02,
0x02,0x06,0x04,0x0C,0x08,0x18,0x10,0x30,0x60,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0x60,
0x30,0x98,0x8C,0xC6,0x43,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x06,0x0C,0x1C,0x38,
0xF8,0x90,0x30,0x20,0x60,0x40,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x06,
0x0C,0x38,0xE0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x83,0xC6,0xDC,0xF8,0x30,
0x10,0x50,0x58,0x18,0x10,0x30,0xE0,0xC0,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0xC0,0xC0,0x40,
0x60,0x60,0x20,0x20,0x30,0x10,0x10,0x18,0x18,0x08,0x08,0x0C,0x0C,0x07,0x87,0x82,
0x83,0xC1,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x30,0x10,0x18,0x18,0x08,0x08,0x08,
0x09,0x1F,0x78,0xC0,0x80,0x80,0x80,0x01,0x03,0x06,0x1C,0x78,0xE0,0x80,0xC0,0xC0,
0x60,0x38,0x1F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x06,
0xFC,0xF8,0xD0,0xD0,0xF4,0xFC,0xF9,0xF9,0x79,0x78,0xFC,0xFC,0x18,0x0D,0x07,0x03,
0x00,0x00,0x80,0xC0,0x70,0x38,0x18,0x0C,0x06,0x03,0x03,0x81,0xC0,0x60,0x20,0x30,
0x18,0x18,0x08,0x0C,0x04,0x06,0x06,0x02,0x02,0x03,0x03,0x03,0x01,0x01,0x01,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0E,0x06,0x00,0x00,0x00,0x00,0x00,
0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0x40,0x60,0x30,0x18,0x1C,0x3F,
0x7F,0xE6,0xC4,0xCC,0x8C,0x0D,0x04,0x04,0x06,0x03,0x03,0x00,0x00,0x00,0x00,0x00,
0xF8,0x7E,0x03,0x00,0x00,0x00,0x00,0x00,0xF0,0x7C,0x07,0x01,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x0C,0x08,0xF8,0xD0,0x10,0x30,0x30,0x20,0x20,
0x20,0x60,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
0x40,0x41,0x61,0x63,0x62,0x26,0x24,0x3C,0x38,0x18,0x18,0x18,0x10,0x10,0x10,0x10,
0x10,0x30,0x30,0x30,0x30,0x30,0x30,0x10,0x10,0x10,0x10,0x10,0x18,0x18,0x08,0x08,
0x08,0x0C,0x04,0x04,0x06,0x02,0x03,0x01,0x01,0x01,0x01,0x03,0x06,0x0C,0x18,0x70,
0xE0,0x60,0x71,0x3F,0x1F,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x1F,0xFE,0xC0,0x00,0x00,0x00,0x00,0x00,0x1F,0x7F,0xE0,0x80,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x80,0x80,0x40,0x60,0x30,0x18,0x0C,0x07,0x01,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xF0,
0x3F,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x01,0x03,0x06,0x0C,0x18,0x10,0x10,0x30,0x20,0x21,0x21,0x23,0x20,0x20,
0x20,0x20,0x20,0x20,0x30,0x30,0x10,0x10,0x18,0x18,0x08,0x0C,0x0C,0x04,0x06,0x02,
0x03,0x01,0x03,0x06,0x0C,0x38,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xF0,0xF8,0xF8,0x0C,
0x04,0x04,0x06,0x06,0x06,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x06,0x06,0x04,0x04,
0x0C,0x08,0xF8,0xF0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xE0,0x30,0x1C,0x07,0x03,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x7F,0x79,0xF0,0xD0,0xD0,0xF0,0xE0,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xC0,0xC0,0xC0,0x40,0x41,0x47,0x6E,0x3B,0x3E,
0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x1C,0x17,0x3B,0x6F,0x7B,0x70,0xD0,0x90,0xF0,0xE0,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0xC0,0xC0,0x7F,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
// 汉字点阵(宽x高=16x16)
// "温湿度℃"
const char hanzi_utf8_index[] = "\xce\xc2\xca\xaa\xb6\xc8\xa1\xe6";
const unsigned char hanzi16x16[][16] = {
// 温
{0x10,0x60,0x02,0x8C,0x00,0x00,0xFE,0x92,0x92,0x92,0x92,0x92,0xFE,0x00,0x00,0x00},
{0x04,0x04,0x7E,0x01,0x40,0x7E,0x42,0x42,0x7E,0x42,0x7E,0x42,0x42,0x7E,0x40,0x00},
// 湿
{0x10,0x60,0x02,0x8C,0x00,0xFE,0x92,0x92,0x92,0x92,0x92,0x92,0xFE,0x00,0x00,0x00},
{0x04,0x04,0x7E,0x01,0x44,0x48,0x50,0x7F,0x40,0x40,0x7F,0x50,0x48,0x44,0x40,0x00},
// 度
{0x00,0x00,0xFC,0x24,0x24,0x24,0xFC,0x25,0x26,0x24,0xFC,0x24,0x24,0x24,0x04,0x00},
{0x40,0x30,0x8F,0x80,0x84,0x4C,0x55,0x25,0x25,0x25,0x55,0x4C,0x80,0x80,0x80,0x00},
//摄氏度符号℃
{0x06,0x09,0x09,0xE6,0xF8,0x0C,0x04,0x02,0x02,0x02,0x02,0x02,0x04,0x1E,0x00,0x00},
{0x00,0x00,0x00,0x07,0x1F,0x30,0x20,0x40,0x40,0x40,0x40,0x40,0x20,0x10,0x00,0x00}
};
/****** ASCII 6*8的点阵字库**********/
const unsigned char ascii6x8[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,// sp
0x00, 0x00, 0x00, 0x2f, 0x00, 0x00,// !
0x00, 0x00, 0x07, 0x00, 0x07, 0x00,// "
0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14,// #
0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12,// $
0x00, 0x62, 0x64, 0x08, 0x13, 0x23,// %
0x00, 0x36, 0x49, 0x55, 0x22, 0x50,// &
0x00, 0x00, 0x05, 0x03, 0x00, 0x00,// '
0x00, 0x00, 0x1c, 0x22, 0x41, 0x00,// (
0x00, 0x00, 0x41, 0x22, 0x1c, 0x00,// )
0x00, 0x14, 0x08, 0x3E, 0x08, 0x14,// *
0x00, 0x08, 0x08, 0x3E, 0x08, 0x08,// +
0x00, 0x00, 0x00, 0xA0, 0x60, 0x00,// ,
0x00, 0x08, 0x08, 0x08, 0x08, 0x08,// -
0x00, 0x00, 0x60, 0x60, 0x00, 0x00,// .
0x00, 0x20, 0x10, 0x08, 0x04, 0x02,// /
0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E,// 0
0x00, 0x00, 0x42, 0x7F, 0x40, 0x00,// 1
0x00, 0x42, 0x61, 0x51, 0x49, 0x46,// 2
0x00, 0x21, 0x41, 0x45, 0x4B, 0x31,// 3
0x00, 0x18, 0x14, 0x12, 0x7F, 0x10,// 4
0x00, 0x27, 0x45, 0x45, 0x45, 0x39,// 5
0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30,// 6
0x00, 0x01, 0x71, 0x09, 0x05, 0x03,// 7
0x00, 0x36, 0x49, 0x49, 0x49, 0x36,// 8
0x00, 0x06, 0x49, 0x49, 0x29, 0x1E,// 9
0x00, 0x00, 0x36, 0x36, 0x00, 0x00,// :
0x00, 0x00, 0x56, 0x36, 0x00, 0x00,// ;
0x00, 0x08, 0x14, 0x22, 0x41, 0x00,// <
0x00, 0x14, 0x14, 0x14, 0x14, 0x14,// =
0x00, 0x00, 0x41, 0x22, 0x14, 0x08,// >
0x00, 0x02, 0x01, 0x51, 0x09, 0x06,// ?
0x00, 0x32, 0x49, 0x59, 0x51, 0x3E,// @
0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C,// A
0x00, 0x7F, 0x49, 0x49, 0x49, 0x36,// B
0x00, 0x3E, 0x41, 0x41, 0x41, 0x22,// C
0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C,// D
0x00, 0x7F, 0x49, 0x49, 0x49, 0x41,// E
0x00, 0x7F, 0x09, 0x09, 0x09, 0x01,// F
0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A,// G
0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F,// H
0x00, 0x00, 0x41, 0x7F, 0x41, 0x00,// I
0x00, 0x20, 0x40, 0x41, 0x3F, 0x01,// J
0x00, 0x7F, 0x08, 0x14, 0x22, 0x41,// K
0x00, 0x7F, 0x40, 0x40, 0x40, 0x40,// L
0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F,// M
0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F,// N
0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E,// O
0x00, 0x7F, 0x09, 0x09, 0x09, 0x06,// P
0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E,// Q
0x00, 0x7F, 0x09, 0x19, 0x29, 0x46,// R
0x00, 0x46, 0x49, 0x49, 0x49, 0x31,// S
0x00, 0x01, 0x01, 0x7F, 0x01, 0x01,// T
0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F,// U
0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F,// V
0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F,// W
0x00, 0x63, 0x14, 0x08, 0x14, 0x63,// X
0x00, 0x07, 0x08, 0x70, 0x08, 0x07,// Y
0x00, 0x61, 0x51, 0x49, 0x45, 0x43,// Z
0x00, 0x00, 0x7F, 0x41, 0x41, 0x00,// [
0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55,// 55
0x00, 0x00, 0x41, 0x41, 0x7F, 0x00,// ]
0x00, 0x04, 0x02, 0x01, 0x02, 0x04,// ^
0x00, 0x40, 0x40, 0x40, 0x40, 0x40,// _
0x00, 0x00, 0x01, 0x02, 0x04, 0x00,// '
0x00, 0x20, 0x54, 0x54, 0x54, 0x78,// a
0x00, 0x7F, 0x48, 0x44, 0x44, 0x38,// b
0x00, 0x38, 0x44, 0x44, 0x44, 0x20,// c
0x00, 0x38, 0x44, 0x44, 0x48, 0x7F,// d
0x00, 0x38, 0x54, 0x54, 0x54, 0x18,// e
0x00, 0x08, 0x7E, 0x09, 0x01, 0x02,// f
0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C,// g
0x00, 0x7F, 0x08, 0x04, 0x04, 0x78,// h
0x00, 0x00, 0x44, 0x7D, 0x40, 0x00,// i
0x00, 0x40, 0x80, 0x84, 0x7D, 0x00,// j
0x00, 0x7F, 0x10, 0x28, 0x44, 0x00,// k
0x00, 0x00, 0x41, 0x7F, 0x40, 0x00,// l
0x00, 0x7C, 0x04, 0x18, 0x04, 0x78,// m
0x00, 0x7C, 0x08, 0x04, 0x04, 0x78,// n
0x00, 0x38, 0x44, 0x44, 0x44, 0x38,// o
0x00, 0xFC, 0x24, 0x24, 0x24, 0x18,// p
0x00, 0x18, 0x24, 0x24, 0x18, 0xFC,// q
0x00, 0x7C, 0x08, 0x04, 0x04, 0x08,// r
0x00, 0x48, 0x54, 0x54, 0x54, 0x20,// s
0x00, 0x04, 0x3F, 0x44, 0x40, 0x20,// t
0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C,// u
0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C,// v
0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C,// w
0x00, 0x44, 0x28, 0x10, 0x28, 0x44,// x
0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C,// y
0x00, 0x44, 0x64, 0x54, 0x4C, 0x44,// z
0x14, 0x14, 0x14, 0x14, 0x14, 0x14,// horiz lines
};
/****** ASCII 8*16的点阵字库**********/
const unsigned char ascii8x16[]= {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// 0
0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00,//! 1
0x00,0x10,0x0C,0x06,0x10,0x0C,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//" 2
0x40,0xC0,0x78,0x40,0xC0,0x78,0x40,0x00,0x04,0x3F,0x04,0x04,0x3F,0x04,0x04,0x00,//# 3
0x00,0x70,0x88,0xFC,0x08,0x30,0x00,0x00,0x00,0x18,0x20,0xFF,0x21,0x1E,0x00,0x00,//$ 4
0xF0,0x08,0xF0,0x00,0xE0,0x18,0x00,0x00,0x00,0x21,0x1C,0x03,0x1E,0x21,0x1E,0x00,//% 5
0x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00,0x1E,0x21,0x23,0x24,0x19,0x27,0x21,0x10,//& 6
0x10,0x16,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//' 7
0x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00,0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00,//( 8
0x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00,0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00,//) 9
0x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00,0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00,//* 10
0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x1F,0x01,0x01,0x01,0x00,//+ 11
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xB0,0x70,0x00,0x00,0x00,0x00,0x00,//, 12
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,//- 13
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,//. 14
0x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04,0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00,/// 15
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,//0 16
0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//1 17
0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,//2 18
0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,//3 19
0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,//4 20
0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,//5 21
0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,//6 22
0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,//7 23
0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,//8 24
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00,//9 25
0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,//: 26
0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x60,0x00,0x00,0x00,0x00,//; 27
0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00,//< 28
0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,//= 29
0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00,//> 30
0x00,0x70,0x48,0x08,0x08,0x08,0xF0,0x00,0x00,0x00,0x00,0x30,0x36,0x01,0x00,0x00,//? 31
0xC0,0x30,0xC8,0x28,0xE8,0x10,0xE0,0x00,0x07,0x18,0x27,0x24,0x23,0x14,0x0B,0x00,//@ 32
0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20,//A 33
0x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00,//B 34
0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00,//C 35
0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00,//D 36
0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00,//E 37
0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00,//F 38
0xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00,0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00,//G 39
0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20,//H 40
0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//I 41
0x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00,//J 42
0x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00,0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00,//K 43
0x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00,//L 44
0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00,//M 45
0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00,//N 46
0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00,//O 47
0x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00,0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00,//P 48
0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00,//Q 49
0x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00,0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20,//R 50
0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00,//S 51
0x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//T 52
0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//U 53
0x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08,0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00,//V 54
0xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00,0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00,//W 55
0x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08,0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20,//X 56
0x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//Y 57
0x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00,0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00,//Z 58
0x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00,//[ 59
0x00,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00,//\ 60
0x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00,//] 61
0x00,0x00,0x04,0x02,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//^ 62
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,//_ 63
0x00,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//` 64
0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20,//a 65
0x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00,//b 66
0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00,//c 67
0x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20,//d 68
0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00,//e 69
0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//f 70
0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00,//g 71
0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//h 72
0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//i 73
0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,//j 74
0x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00,0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00,//k 75
0x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//l 76
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F,//m 77
0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//n 78
0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//o 79
0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00,//p 80
0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80,//q 81
0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00,//r 82
0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00,//s 83
0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00,//t 84
0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20,//u 85
0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00,//v 86
0x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80,0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00,//w 87
0x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00,//x 88
0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00,//y 89
0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00,//z 90
0x00,0x00,0x00,0x00,0x80,0x7C,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40,//{ 91
0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,//| 92
0x00,0x02,0x02,0x7C,0x80,0x00,0x00,0x00,0x00,0x40,0x40,0x3F,0x00,0x00,0x00,0x00,//} 93
0x00,0x06,0x01,0x01,0x02,0x02,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//~ 94
};
+17
View File
@@ -0,0 +1,17 @@
#ifndef __WFONT_H
#define __WFONT_H
// 小象的图片
extern const unsigned char elephant128x64[];
// 汉字点阵(宽x高=16x16)
extern const char hanzi_utf8_index[];
extern const unsigned char hanzi16x16[][16];
/****** ASCII 6*8的点阵字库**********/
extern const unsigned char ascii6x8[];
/****** ASCII 8*16的点阵字库**********/
extern const unsigned char ascii8x16[];
#endif // __WFONT_H