【51单片机实验笔记】前篇(三) 模块功能封装汇总(持续更新)

这篇具有很好参考价值的文章主要介绍了【51单片机实验笔记】前篇(三) 模块功能封装汇总(持续更新)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


通用函数(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)

主要实现了延时法刷新定时器法刷新两种方式。提供字符静态写入函数整数写入函数浮点数写入函数字符串写入函数

主要解决了小数点显示和负号显示的问题。

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模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 51单片机 | 外部中断实验

       51 单片机外部中断有 2 个,外部中断 0 和外部中断 1 ,它们的使用方法是一样的,所以只要学会一个即可掌握所有外部中断使用。本节所要实现的功能是:使用独立按键 K3 控制 LED 亮灭, K3 连接外部中断 0 ( P3.2 )管脚。   上一节我们介绍了 51 单片机的中断系统,我

    2023年04月26日
    浏览(53)
  • 51单片机 | 串口通信实验

      这一节我们就来学习 51 单片机的串口通信。开发板上集成了 1 个串口通信电路,是 USB 转串口模块,它既可下载程序也可实现串口通信功能。本节要实现的功能是: 51 单片机通过串口( UART )实现与 PC 机对话, 51 单片机的串口收到 PC 机发来的数据后原封不动的返回给

    2024年02月04日
    浏览(64)
  • 【【51单片机AD转换模块】】

    2024年02月15日
    浏览(41)
  • 51单片机(ESP8266模块)

    蓝牙,ESP-01s,Zigbee, NB-Iot等通信模块都是基于AT指令的设计 AT指令集是从终端设备(Terminal Equipment,TE)或数据终端设备(Data Terminal Equipment,DTE)向终端适配器(Terminal Adapter,TA)或数据电路终端设备(Data Circuit Terminal Equipment,DCE)发送的。 其对所传输的数据包大小有定义:即对于

    2024年02月06日
    浏览(37)
  • 51单片机——LCD1602模块

    一.LCD1602介绍 1.LCD1602 (Liquid Crystal Display )液晶显示屏是一种字符型液晶显示模块,可以显示ASCII码的标准字符和其它的一些内置特殊字符,还可以有8个自定义字符。 2.显示容量:16x2个字符,每个字符为5*7点阵。 二.LCD1602接口介绍 引脚 功能 VSS 接地 VDD 电源正极(4.5v-5.5v) VO 对

    2024年02月07日
    浏览(41)
  • 【【51单片机DA转换模块】】

    2024年02月14日
    浏览(38)
  • 51单片机实验课一

     实验现象单片机从P2_0——P2_7逐个点亮LED(始终只有一个亮,呈现LED流水灯的形式) 直到P2_7的LED灯点亮之后再熄灭,P2_0的LED灯又点亮,如此循环往复  程序讲解: 在for循环中,让流水灯的程序循环八次 P2=P21; 因为LED灯为共阳极,所以为低电平点亮,我们将P2端口数值左移一

    2024年01月23日
    浏览(32)
  • 51单片机点灯实验(含程序+仿真+硬件实验)

    一、实验原理 LED发光二极管核心为PN结,单向导电,有阴极和阳极,两极均可以控制,需要亮起来,电流不能过大和过小,过大,烧坏二极管,过小,电光效应弱,发光不明显,引入“限流电路”。为减少I/O引脚的消耗,一般控制一极,有阳极控制法和阴极控制法。阳极控制

    2024年02月04日
    浏览(54)
  • 51单片机实验02- P0口流水灯实验

    目录 一、实验的背景和意义 二、实验目的 三、实验步骤 四、实验仪器 五、实验任务及要求  1,从led4开始右移 1)思路  ①起始灯 (led4) ②右移 2)效果 3)代码☀  2,从其他小灯并向右依次点亮其他小灯  1)从led3开始右移 2)从led5开始右移 3)从led6开始右移 4)从le

    2024年04月12日
    浏览(36)
  • 【【51单片机LCD1602模块介绍】】

    显示容量16x2 每个字符是5x7的点阵 VDD 是电源正极 4.5-5.5v VO 是对比度调节电压 RS 数据/指令 选择 1为数据0为指令 RW 读写选择1是读 0为写 E 使能 1为数据有效 下降沿执行命令 D0-D7 数据输入输出 A 背光电源正极 K 背光电源负极 LCD1602的操作流程 1.初始化: 发送0x38//八位数据接口,

    2024年02月15日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包