包含常用头文件,宏定义,自定义类型,函数工具等。
#ifndef _PUBLIC_H_
#define _PUBLIC_H_
/*---------------------常用头文件---------------------------------*/
#include
#include
#include
#include
#include
#define false 0
#define true 1
typedef unsigned char u8;
typedef unsigned int u16;
void delay_10us(u16);
void delay_ms(u16);
u8 * int2String(int, bit);
u8 * float2String(float, u8);
#endif
#include "public.h"
/**
** @brief 通用函数
** @author QIU
** @data 2023.09.03
**/
/*-------------------------------------------------------------------*/
/**
** @brief 延时函数(10us)
** @param t:0~65535,循环一次约10us
** @retval 无
**/
void delay_10us(u16 t){
while(t--);
}
/**
** @brief 延时函数(ms)
** @param t:0~65535,单位ms
** @retval 无
**/
void delay_ms(u16 t){
while(t--){
delay_10us(100);
}
}
/**
** @brief 整数转字符串
** @param num:接受整型值
** @param sign:是否带符号
** @retval 返回字符串指针
**/
u8 * int2String(int num, bit sign){
static u8 str[8];
// 是否带符号
if(sign){
sprintf(str, "%d", num);
}else{
sprintf(str, "%u", num);
}
// 返回指针
return str;
}
/**
** @brief 浮点数转字符串
** @param num:接受浮点数
** @param len:指定精度,小数点位数0~6(四舍五入)
** @retval 返回字符串指针
**/
u8 * float2String(float num, u8 len){
static u8 str[10];
// 筛选
switch(len){
case 0: sprintf(str, "%.0f", num); break;
case 1: sprintf(str, "%.1f", num); break;
case 2: sprintf(str, "%.2f", num); break;
case 3: sprintf(str, "%.3f", num); break;
case 4: sprintf(str, "%.4f", num); break;
case 5: sprintf(str, "%.5f", num); break;
default: sprintf(str, "%f", num); break; // 默认6位小数
}
// 返回指针
return str;
}
包含常用延时函数。通用函数兼容延时函数。
#ifndef _DELAY_H_
#define _DELAY_H_
#include
#define false 0
#define true 1
typedef unsigned char u8;
typedef unsigned int u16;
void delay_10us(u16);
void delay_ms(u16);
#endif
#include "delay.h"
/**
** @brief 通用函数
** @author QIU
** @data 2023.08.23
**/
/*-------------------------------------------------------------------*/
/**
** @brief 延时函数(10us)
** @param t:0~65535,循环一次约10us
** @retval 无
**/
void delay_10us(u16 t){
while(t--);
}
/**
** @brief 延时函数(ms)
** @param t:0~65535,单位ms
** @retval 无
**/
void delay_ms(u16 t){
while(t--){
delay_10us(100);
}
}
主要实现了延时法刷新和定时器法刷新两种方式。提供字符串写入函数。
#ifndef _SMG_H_
#define _SMG_H_
#include "public.h"
#define SMG_PORT P0
// 位选引脚,与38译码器相连
sbit A1 = P2^2;
sbit A2 = P2^3;
sbit A3 = P2^4;
void smg_showString(u8*, u8);
void smg_showString_Bytimer(u8*, u8);
#endif
#include "smg.h"
/**
** @brief 数码管封装
** 1. 延时刷新
** 2. 定时器刷新
** @author QIU
** @date 2023.09.03
**/
/*-------------------------------------------------------------------*/
//共阴极数码管字形码编码
u8 code smgduan[] = {0x3f,0x06,0x5b,0x4f,0x66, //0 1 2 3 4
0x6d,0x7d,0x07,0x7f,0x6f, //5 6 7 8 9
0x77,0x7c,0x58,0x5e,0x79, //A b c d E
0x71,0x76,0x30,0x0e,0x38, //F H I J L
0x54,0x3f,0x73,0x67,0x50, //n o p q r
0x6d,0x3e,0x3e,0x6e,0x40};//s U v y -
/**
** @brief 指定第几个数码管点亮,38译码器控制位选(不对外声明)
** @param pos:从左至右,数码管位置 1~8
** @retval 无
**/
void select_38(u8 pos){
u8 temp_pos = 8 - pos; // 0~7
A1 = temp_pos % 2; //高位
temp_pos /= 2;
A2 = temp_pos % 2;
temp_pos /= 2;
A3 = temp_pos % 2; //低位
}
/**
** @brief 解析数据并取得相应数码管字形码编码
** @param dat:想要显示的字符
** @retval 对应字形码编码值
**/
u8 parse_data(u8 dat){
switch(dat){
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':return smgduan[dat-'0'];
case 'a':
case 'A':return smgduan[10];
case 'b':
case 'B':return smgduan[11];
case 'c':
case 'C':return smgduan[12];
case 'd':
case 'D':return smgduan[13];
case 'e':
case 'E':return smgduan[14];
case 'f':
case 'F':return smgduan[15];
case 'h':
case 'H':return smgduan[16];
case 'i':
case 'I':return smgduan[17];
case 'j':
case 'J':return smgduan[18];
case 'l':
case 'L':return smgduan[19];
case 'n':
case 'N':return smgduan[20];
case 'o':
case 'O':return smgduan[21];
case 'p':
case 'P':return smgduan[22];
case 'q':
case 'Q':return smgduan[23];
case 'r':
case 'R':return smgduan[24];
case 's':
case 'S':return smgduan[25];
case 'u':
case 'U':return smgduan[26];
case 'v':
case 'V':return smgduan[27];
case 'y':
case 'Y':return smgduan[28];
case '-':return smgduan[29];
default:return 0x00; //不显示
}
}
/**
** @brief 根据输入的ASCII码,显示对应字符(1字节)
** @param dat:字符数据,或其ASCII值
** @param pos:显示位置 1~8
** @retval 无
**/
void smg_showChar(u8 dat, u8 pos, bit flag){
// 解析点亮哪一个数码管
select_38(pos);
// 解析数据
SMG_PORT = parse_data(dat);
// 加标点
if(flag) SMG_PORT |= 0x80;
}
/*-------------------------------------------------------------------*/
/*-----------------------延时法刷新----------------------------------*/
/*-------------------------------------------------------------------*/
/**
** @brief 延时法刷新
** @param dat:字符数组,需以'\0'结尾
** @param pos:显示位置
** @param dot:小数点位置
** @retval 无
**/
void smg_flush_Bydelay(u8 dat[], u8 pos, u8 dot){
u8 i;
// 超出部分直接截断
for(i=0;(i<9-pos)&&(dat[i]!='\0');i++){
// 如果是小数点,跳过,往前移一位
if(dat[i] == '.'){
pos -= 1;
continue;
}
// 显示
smg_showChar(dat[i], pos+i, (dot == i+1)?true:false);
// 延时1ms
delay_ms(1);
// 消影
SMG_PORT = 0x00;
}
}
/**
** @brief 显示字符串(动态显示)
** @param dat:字符数组,需以'\0'结尾
** @param pos:显示位置
** @retval 无
**/
void smg_showString(u8 dat[], u8 pos){
u8 i = 0, dot = 0;
// 先判断是否存在小数点
while(dat[i]!='\0'){
if(dat[i] == '.') break;
i++;
}
// 记录下标点位置
if(i < strlen(dat)) dot = i;
// 延时法刷新
smg_flush_Bydelay(dat, pos, dot);
}
/*-------------------------------------------------------------------*/
/*--------------------------定时器法刷新-----------------------------*/
/*-------------------------------------------------------------------*/
/**
** @brief 数码管显示字符串(定时器法刷新)
** @param dat:字符数组,需以'\0'结尾
** @param pos:显示位置
** @retval 返回值
**/
void smg_showString_Bytimer(u8 dat[], u8 pos){
// 数码管计数器, 小数点位置
static u8 smg_counter = 0, dot_counter = 0, dot_port[8];
// 暂存当前位置
u8 temp;
// 先消影
SMG_PORT = 0x00;
// 如果是小数点,跳出。
if(dat[smg_counter] == '.'){
// 记录小数点位置,下一轮刷新
dot_port[smg_counter-1] = true;
// 计数器后移一位
smg_counter++;
// 小数点计数器自增
dot_counter++;
return;
}
// 计算当前位置
temp = pos+smg_counter-dot_counter;
// 判断是否加小数点(检测到小数点的后面几位整体前移)
smg_showChar(dat[smg_counter], temp, dot_port[smg_counter]);
// 如果是结束符,跳出(超出部分截断)
if(temp == 8 | dat[smg_counter] == '\0'){
// 重置
smg_counter = 0;
// 根据标志决定是否清除小数点
if(dot_counter){
// 清零
dot_counter = 0;
}else{
// 清空
strcpy(dot_port, "");
}
return;
}else{
smg_counter++;
}
}