通用函数(2023.09.03)
包含常用头文件,宏定义,自定义类型,函数工具等。
public.h
#ifndef _PUBLIC_H_
#define _PUBLIC_H_
/*---------------------常用头文件---------------------------------*/
#include <REGX52.H>
#include <intrins.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#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
public.c
#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;
}
延时函数(2023.08.23)
包含常用延时函数。通用函数兼容延时函数。
delay.h
#ifndef _DELAY_H_
#define _DELAY_H_
#include <REGX52.H>
#define false 0
#define true 1
typedef unsigned char u8;
typedef unsigned int u16;
void delay_10us(u16);
void delay_ms(u16);
#endif
delay.c
#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);
}
}
LED模块(2023.08.23)
包含常用LED
显示函数。
led.h
#ifndef _LED_H_
#define _LED_H_
#include "delay.h"
#define LED_PORT P2
void led_on(u8);
void led_turn(u8);
void led_stream(u16);
void led_run(u16);
#endif
led.c
#include "led.h"
/**
** @brief LED控制程序
** @author QIU
** @data 2023.08.23
**/
/*-------------------------------------------------------------------*/
/**
** @brief 指定某个LED亮
** @param pos: 位置(1~8)
** @retval 无
**/
void led_on(u8 pos){
LED_PORT &= ~(0x01<<(pos-1));
}
/**
** @brief 指定某个LED灭
** @param pos: 位置(1~8)
** @retval 无
**/
void led_off(u8 pos){
LED_PORT |= 0x01<<(pos-1);
}
/**
** @brief 指定位置LED翻转
** @param pos:1—8
** @retval 无
**/
void led_turn(u8 pos){
u8 port;
port = (LED_PORT>>(pos-1))&0x01;
if(port){
led_on(pos);
}else{
led_off(pos);
}
}
/**
** @brief LED流水灯
** @param time 延时时间
** @retval 无
**/
void led_stream(u16 time){
u8 i;
for(i=0;i<8;i++){
led_on(i+1);
delay_10us(time);
}
// 全部熄灭
for(i=0;i<8;i++){
led_off(i+1);
}
}
/**
** @brief LED跑马灯
** @param time 延时时间
** @retval 无
**/
void led_run(u16 time){
u8 i;
for(i=0;i<8;i++){
led_on(i+1);
delay_10us(time);
led_off(i+1);
}
}
数码管模块(2024.01.31)
主要实现了延时法刷新和定时器法刷新两种方式。提供字符静态写入函数、整数写入函数、浮点数写入函数和字符串写入函数。
主要解决了小数点显示和负号显示的问题。文章来源:https://www.toymoban.com/news/detail-696232.html
smg.h
#ifndef _SMG_H_
#define _SMG_H_
#include "delay.h"
#define SMG_PORT P0
// 位选引脚,与38译码器相连
sbit A1 = P2^2;
sbit A2 = P2^3;
sbit A3 = P2^4;
void smg_showChar(u8, u8, bit);
void smg_showString(u8*, u8);
void smg_showInt(int, u8);
void smg_showFloat(double, u8, u8);
#endif
smg.c
#include "smg.h"
#include <stdio.h>
#include <math.h>
#include <string.h>
/**
** @brief 数码管封装
** 1. 字符静态显示:仅需一次输入。输入字符。可用于初始清屏。
** 2. 字符串数据动态显示:包含延时法和定时器法。
** 3. 浮点型数据动态显示:包含延时法和定时器法。可以显示小数。
** 4. 整型数据动态显示:包含延时法和定时器法。可以显示负数。
** @author QIU
** @date 2024.01.31
**/
/*-------------------------------------------------------------------*/
//共阴极数码管字形码编码
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_cycle(u8 dat[], u8 pos, u8 dot){
u8 i;
// 超出部分直接截断
for(i=0;(i<9-pos)&&(dat[i]!='\0');i++){
// 如果是小数点,跳过,往前移一位
if(dat[i] == '.'){
pos -= 1;
continue;
}
if(dot == i+1){
smg_showChar(dat[i], pos+i, true);
}else{
smg_showChar(dat[i], pos+i, false);
}
delay_ms(1); //延时1ms
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_cycle(dat, pos, dot);
}
/**
** @brief 数码管显示整数(含正负)
** @param dat: 整数
** @param pos: 显示位置
** @retval 无
**/
void smg_showInt(int dat, u8 pos){
xdata u8 temp[9];
sprintf(temp, "%d", dat); // 含正负
smg_showString(temp, pos);
}
/**
** @brief 数码管显示浮点数(含小数点)
** @param dat: 浮点数
** @param len: 指定精度
** @param pos: 显示位置
** @retval 无
**/
void smg_showFloat(double dat, u8 len, u8 pos){
xdata u8 temp[10];
int dat_now;
dat_now = dat * pow(10, len) + 0.5 * (dat>0?1:-1); // 四舍五入(正负),由于浮点数存在误差,结果未必准确
sprintf(temp, "%d", dat_now); // 含正负
smg_cycle(temp, pos, len?(strlen(temp) - len):0);
}
LED点阵模块(2023.08.23)
本质上是对驱动芯片74HC595
的驱动逻辑的封装。文章来源地址https://www.toymoban.com/news/detail-696232.html
LED_Matrix.h
#ifndef _LED_MATRIX_
#define _LED_MATRIX_
#include "delay.h"
void LED_Init();
void LED_Animation_Show(u8 ,u8);
#endif
LED_Matrix.c
#include "LED_Matrix.h"
/**
** @brief LED点阵封装(74HC595芯片驱动代码)
** @author QIU
** @data 2023.08.23
**/
/*-------------------------------------------------------------------*/
/**
** @brief 74HC595芯片(串转并)驱动代码
** @param dat:8位串行数据
** @retval 无
**/
void LED_control(u8 dat){
u8 i;
//将一个字节拆分成串行输入
for(i=0;i<8;i++){
SER = dat >> 7; //先将最高位送入SER中
dat <<= 1; //左移1位(去掉最高位)更新数据
SH = 0; //给移位寄存器时序脉冲
delay_10us(1);
SH = 1; //检测到上升沿时将SER数据读入移位寄存器中
delay_10us(1);
}
ST = 0; //当一个字节传输完毕,此时移位寄存器已满。给存储寄存器时序脉冲
delay_10us(1);
ST = 1;//检测到上升沿时将移位寄存器中的8位数据全部读入存储寄存器中。通过并行输出引脚可以直接检测到
delay_10us(1);
}
/**
** @brief 清屏函数
** @param 无
** @retval 无
**/
void LED_Init(){
LED_Matrix_PORT = 0xff;
}
/**
** @brief 显示对应静态画面(8*8)
** @param datX:阴极,datY:阳极
** @retval 无
**/
void LED_Animation_Show(u8 datX, u8 datY){
LED_control(datY); //阳极码
LED_Matrix_PORT = ~(0x80>>datX);
delay_10us(100);
LED_Init(); //消影
}
独立按键模块
矩阵按键模块
外部中断模块
定时器模块
串口通讯模块
ADC模块
PWM模块
到了这里,关于【51单片机实验笔记】前篇(三) 模块功能封装汇总(持续更新)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!