c51单片机学习笔记二
目录
前言
独立按键实验
矩阵按键实验
IO 扩展(串转并)-74HC595实验
LED 点阵实验
LED点阵点亮一个点
LED点阵点亮数字
LED点阵点亮图像
直流电机实验
步进电机实验
总结
前言
基于普中单片机对51单片机进行学习
注:本篇笔记主要参考了普中单片机开发文档
独立按键实验
按键管脚两端距离长的表示默认是导通状态,距离短的默认是断开状态, 如果按键按下,初始导通状态变为断开,初始断开状态变为导通。
#include "reg52.h"
typedef unsigned int u16; //对系统默认数据类型进行重定义
typedef unsigned char u8;//定义独立按键控制脚
sbit KEY1=P3^1;
sbit KEY2=P3^0;
sbit KEY3=P3^2;
sbit KEY4=P3^3;//定义 LED1 控制脚
sbit LED1=P2^0;//使用宏定义独立按键按下的键值
#define KEY1_PRESS 1
#define KEY2_PRESS 2
#define KEY3_PRESS 3
#define KEY4_PRESS 4
#define KEY_UNPRESS 0void delay_10us(u16 ten_us)
{while(ten_us--);
}u8 key_scan(u8 mode)
{static u8 key=1;if(mode)key=1;//连续扫描按键if(key==1&&(KEY1==0||KEY2==0||KEY3==0||KEY4==0))//任意按键按下{delay_10us(1000);//消抖key=0;if(KEY1==0)return KEY1_PRESS;else if(KEY2==0)return KEY2_PRESS;else if(KEY3==0)return KEY3_PRESS;else if(KEY4==0)return KEY4_PRESS;}else if(KEY1==1&&KEY2==1&&KEY3==1&&KEY4==1) //无按键按下{key=1;}return KEY_UNPRESS;
}void main()
{u8 key=0;while(1){key=key_scan(0);if(key==KEY1_PRESS)//检测按键 K1 是否按下LED1=!LED1;//LED1 状态翻转}
}
解析:
矩阵按键实验
#include "reg52.h"
typedef unsigned int u16; //对系统默认数据类型进行重定义
typedef unsigned char u8;#define KEY_MATRIX_PORT P1 //使用宏定义矩阵按键控制口
#define SMG_A_DP_PORT P0 //使用宏定义数码管段码口
//共阴极数码管显示 0~F 的段码数据
u8 gsmg_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};void delay_10us(u16 ten_us)
{while(ten_us--);
}u8 key_matrix_ranks_scan(void)
{u8 key_value=0;KEY_MATRIX_PORT=0xf7;//给第一列赋值 0,其余全为 1if(KEY_MATRIX_PORT!=0xf7)//判断第一列按键是否按下{delay_10us(1000);//消抖switch(KEY_MATRIX_PORT)//保存第一列按键按下后的键值{case 0x77: key_value=1;break;case 0xb7: key_value=5;break;case 0xd7: key_value=9;break;case 0xe7: key_value=13;break;}}while(KEY_MATRIX_PORT!=0xf7);//等待按键松开KEY_MATRIX_PORT=0xfb;//给第二列赋值 0,其余全为 1if(KEY_MATRIX_PORT!=0xfb)//判断第二列按键是否按下{delay_10us(1000);//消抖switch(KEY_MATRIX_PORT)//保存第二列按键按下后的键值{case 0x7b: key_value=2;break;case 0xbb: key_value=6;break;case 0xdb: key_value=10;break;case 0xeb: key_value=14;break;}}while(KEY_MATRIX_PORT!=0xfb);//等待按键松开KEY_MATRIX_PORT=0xfd;//给第三列赋值 0,其余全为 1if(KEY_MATRIX_PORT!=0xfd)//判断第三列按键是否按下{delay_10us(1000);//消抖switch(KEY_MATRIX_PORT)//保存第三列按键按下后的键值{case 0x7d: key_value=3;break;case 0xbd: key_value=7;break;case 0xdd: key_value=11;break;case 0xed: key_value=15;break;}}while(KEY_MATRIX_PORT!=0xfd);//等待按键松开KEY_MATRIX_PORT=0xfe;//给第四列赋值 0,其余全为 1if(KEY_MATRIX_PORT!=0xfe)//判断第四列按键是否按下{delay_10us(1000);//消抖switch(KEY_MATRIX_PORT)//保存第四列按键按下后的键值{case 0x7e: key_value=4;break;case 0xbe: key_value=8;break;case 0xde: key_value=12;break;case 0xee: key_value=16;break;}}while(KEY_MATRIX_PORT!=0xfe);//等待按键松开return key_value;
}void main()
{u8 key=0;while(1){key=key_matrix_ranks_scan();if(key!=0)SMG_A_DP_PORT=gsmg_code[key-1];//得到的按键值减 1 换算成数组下标对应 0-F 段码}
}
解析:通过key_matrix_ranks_scan按键扫描函数利用行列式扫描原理用for循环判断哪个按键被按下并返回,在主函数中通过判断按键的值来将按键按下的值换算成数码管数组的下标从而显示0~F。
线翻转法实现
原理:两次if和switch语句,先找到列或行低电平后,翻转列或行再测量低电平判断是哪个按键被按下。
代码
#include "reg52.h"
typedef unsigned int u16; //对系统默认数据类型进行重定义
typedef unsigned char u8;
#define KEY_MATRIX_PORT P1 //使用宏定义矩阵按键控制口
#define SMG_A_DP_PORT P0 //使用宏定义数码管段码口
//共阴极数码管显示 0~F 的段码数据
u8 gsmg_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};void delay_10us(u16 ten_us)
{
while(ten_us--);
}u8 key_matrix_flip_scan(void)
{static u8 key_value=0;KEY_MATRIX_PORT=0x0f;//给所有行赋值 0,列全为 1if(KEY_MATRIX_PORT!=0x0f)//判断按键是否按下{delay_10us(1000);//消抖if(KEY_MATRIX_PORT!=0x0f){//测试列KEY_MATRIX_PORT=0x0f;switch(KEY_MATRIX_PORT)//保存行为 0,按键按下后的列值{case 0x07: key_value=1;break;case 0x0b: key_value=2;break;case 0x0d: key_value=3;break;case 0x0e: key_value=4;break;}//测试行KEY_MATRIX_PORT=0xf0;switch(KEY_MATRIX_PORT)//保存列为 0,按键按下后的键值{case 0x70: key_value=key_value;break;case 0xb0: key_value=key_value+4;break;case 0xd0: key_value=key_value+8;break;case 0xe0: key_value=key_value+12;break;}while(KEY_MATRIX_PORT!=0xf0);//等待按键松开}elsekey_value=0;return key_value;
}void main()
{u8 key=0;while(1){key=key_matrix_ranks_scan();if(key!=0)SMG_A_DP_PORT=gsmg_code[key-1];//得到的按键值减 1 换算成数组下标对应 0-F 段码}
}
解析:通过key_matrix_flip_scan函数利用线翻转式原理设置两次if switch进行扫描获取返回值,在主函数中通过判断按键的值来将按键按下的值换算成数码管数组的下标从而显示0~F。
IO 扩展(串转并)-74HC595实验
#include "reg52.h"typedef unsigned int u16; //对系统默认数据类型进行重定义
typedef unsigned char u8;//定义 74HC595 控制管脚
sbit SRCLK=P3^6; //移位寄存器时钟输入
sbit RCLK=P3^5; //存储寄存器时钟输入
sbit SER=P3^4; //串行数据输入#define LEDDZ_COL_PORT P0 //点阵列控制端口
u8 ghc595_buf[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};void delay_10us(u16 ten_us)
{while(ten_us--);
}void delay_ms(u16 ms)
{u16 i,j;for(i=ms;i>0;i--)for(j=110;j>0;j--);
}void hc595_write_data(u8 dat)
{u8 i=0;for(i=0;i<8;i++)//循环 8 次即可将一个字节写入寄存器中{SER=dat>>7;//优先传输一个字节中的高位dat<<=1;//将低位移动到高位SRCLK=0;delay_10us(1);SRCLK=1;delay_10us(1);//移位寄存器时钟上升沿将端口数据送入寄存器中}RCLK=0;delay_10us(1);RCLK=1;//存储寄存器时钟上升沿将前面写入到寄存器的数据输出
}void main()
{u8 i=0;LEDDZ_COL_PORT=0x00;//将 LED 点阵列全部设置为 0,即 LED 阴极为低电平while(1){for(i=0;i<8;i++){hc595_write_data(0x00);//消除前面寄存器缓存数据hc595_write_data(ghc595_buf[i]);//写入新的数据delay_ms(500);//延时 500ms}}
}
解析:
LED 点阵实验
LED点阵点亮一个点
#include "reg51.h"typedef unsigned int u16; //对系统默认数据类型进行重定义
typedef unsigned char u8;//定义74HC595控制管脚
sbit SRCLK=P3^6; //移位寄存器时钟输入
sbit RCLK=P3^5; //存储寄存器时钟输入
sbit SER=P3^4; //串行数据输入#define LEDDZ_COL_PORT P0 //点阵列控制端口void delay_10us(u16 ten_us)
{while(ten_us--);
}void hc595_write_data(u8 dat)
{u8 i=0;for(i=0;i<8;i++)//循环8次即可将一个字节写入寄存器中{SER=dat>>7;//优先传输一个字节中的高位dat<<=1;//将低位移动到高位SRCLK=0;delay_10us(1);SRCLK=1;delay_10us(1);//移位寄存器时钟上升沿将端口数据送入寄存器中 }RCLK=0;delay_10us(1);RCLK=1;//存储寄存器时钟上升沿将前面写入到寄存器的数据输出
}void main()
{ u8 i=0;LEDDZ_COL_PORT=0x7f;//将LED点阵左边第一列设置为0,即LED阴极为低电平,其余列为1,即高电平while(1){ hc595_write_data(0x80);//将LED点阵上边第一行设置为1,即LED阳极为高电平,其余行为0,即低电平 }
}
解析:
将第一个点对应的行为高电平,列为低电平即可。也就是让 74HC595 输出 0X80(1000 0000),这样点阵第一行就是高电平, 而 P0 口输出 0X7F(0111 1111),这样点阵第一列就是低电平,从而让 LED 点阵第一个点点亮。
LED点阵点亮数字
#include "reg51.h"typedef unsigned int u16; //对系统默认数据类型进行重定义
typedef unsigned char u8;//定义74HC595控制管脚
sbit SRCLK=P3^6; //移位寄存器时钟输入
sbit RCLK=P3^5; //存储寄存器时钟输入
sbit SER=P3^4; //串行数据输入#define LEDDZ_COL_PORT P0 //点阵列控制端口//u8 gled_row[8]={0x00,0x7C,0x82,0x82,0x82,0x7C,0x00,0x00};//LED点阵显示数字0的行数据
u8 gled_row1[8]={0x1E,0x3F,0x7F,0xFE,0xFE,0x7F,0x3F,0x1E};
//u8 gled_row2[8]={0x00,0x1C,0x14,0xFF,0x14,0x1C,0x00,0x00};
u8 gled_col[8]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};//LED点阵显示数字0的列数据void delay_10us(u16 ten_us)
{while(ten_us--);
}void hc595_write_data(u8 dat)
{u8 i=0;for(i=0;i<8;i++)//循环8次即可将一个字节写入寄存器中{SER=dat>>7;//优先传输一个字节中的高位dat<<=1;//将低位移动到高位SRCLK=0;delay_10us(1);SRCLK=1;delay_10us(1);//移位寄存器时钟上升沿将端口数据送入寄存器中 }RCLK=0;delay_10us(1);RCLK=1;//存储寄存器时钟上升沿将前面写入到寄存器的数据输出
}void main()
{ u8 i=0;while(1){ for(i=0;i<8;i++)//循环8次扫描8行、列{LEDDZ_COL_PORT=gled_col[i];//传送列选数据hc595_write_data(gled_row1[i]);//传送行选数据delay_10us(100000);//延时一段时间,等待显示稳定hc595_write_data(0x00);//消影 } }
}
LED点阵点亮图像
实现的功能:LED点阵点亮图像。
#include "reg51.h"typedef unsigned int u16; //对系统默认数据类型进行重定义
typedef unsigned char u8;//定义74HC595控制管脚
sbit SRCLK=P3^6; //移位寄存器时钟输入
sbit RCLK=P3^5; //存储寄存器时钟输入
sbit SER=P3^4; //串行数据输入#define LEDDZ_COL_PORT P0 //点阵列控制端口u8 gled_row[8]={0x38,0x7C,0x7E,0x3F,0x3F,0x7E,0x7C,0x38};//LED点阵显示图像的行数据
u8 gled_col[8]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};//LED点阵显示图像的列数据void delay_10us(u16 ten_us)
{while(ten_us--);
}void hc595_write_data(u8 dat)
{u8 i=0;for(i=0;i<8;i++)//循环8次即可将一个字节写入寄存器中{SER=dat>>7;//优先传输一个字节中的高位dat<<=1;//将低位移动到高位SRCLK=0;delay_10us(1);SRCLK=1;delay_10us(1);//移位寄存器时钟上升沿将端口数据送入寄存器中 }RCLK=0;delay_10us(1);RCLK=1;//存储寄存器时钟上升沿将前面写入到寄存器的数据输出
}void main()
{ u8 i=0;while(1){ for(i=0;i<8;i++)//循环8次扫描8行、列{LEDDZ_COL_PORT=gled_col[i];//传送列选数据hc595_write_data(gled_row[i]);//传送行选数据delay_10us(100);//延时一段时间,等待显示稳定hc595_write_data(0x00);//消影 } }
}
直流电机实验
#include "reg52.h"typedef unsigned int u16; //对系统默认数据类型进行重定义
typedef unsigned char u8;//定义直流电机控制管脚
sbit DC_Motor=P1^0;#define DC_MOTOR_RUN_TIME 5000 //定义直流电机运行时间为5000msvoid delay_ms(u16 ms)
{u16 i,j;for(i=ms;i>0;i--)for(j=110;j>0;j--);
}void main()
{ DC_Motor=1;//开启电机delay_ms(DC_MOTOR_RUN_TIME);DC_Motor=0;//关闭电机while(1){ }
}
步进电机实验
#include "reg52.h"typedef unsigned int u16; //对系统默认数据类型进行重定义
typedef unsigned char u8;//定义ULN2003控制步进电机管脚
sbit IN1_A=P1^0;
sbit IN2_B=P1^1;
sbit IN3_C=P1^2;
sbit IN4_D=P1^3;//定义独立按键控制脚
sbit KEY1=P3^1;
sbit KEY2=P3^0;
sbit KEY3=P3^2;
sbit KEY4=P3^3;//使用宏定义独立按键按下的键值
#define KEY1_PRESS 1
#define KEY2_PRESS 2
#define KEY3_PRESS 3
#define KEY4_PRESS 4
#define KEY_UNPRESS 0// 定义步进电机速度,值越小,速度越快
// 最小不能小于1
#define STEPMOTOR_MAXSPEED 1
#define STEPMOTOR_MINSPEED 5 void delay_10us(u16 ten_us)
{while(ten_us--);
}void delay_ms(u16 ms)
{u16 i,j;for(i=ms;i>0;i--)for(j=110;j>0;j--);
}void step_motor_28BYJ48_send_pulse(u8 step,u8 dir)
{u8 temp=step;if(dir==0) //如果为逆时针旋转temp=7-step;//调换节拍信号switch(temp)//8个节拍控制:A->AB->B->BC->C->CD->D->DA{case 0: IN1_A=1;IN2_B=0;IN3_C=0;IN4_D=0;break;case 1: IN1_A=1;IN2_B=1;IN3_C=0;IN4_D=0;break;case 2: IN1_A=0;IN2_B=1;IN3_C=0;IN4_D=0;break;case 3: IN1_A=0;IN2_B=1;IN3_C=1;IN4_D=0;break;case 4: IN1_A=0;IN2_B=0;IN3_C=1;IN4_D=0;break;case 5: IN1_A=0;IN2_B=0;IN3_C=1;IN4_D=1;break;case 6: IN1_A=0;IN2_B=0;IN3_C=0;IN4_D=1;break;case 7: IN1_A=1;IN2_B=0;IN3_C=0;IN4_D=1;break;default: IN1_A=0;IN2_B=0;IN3_C=0;IN4_D=0;break;//停止相序 }
}u8 key_scan(u8 mode)
{static u8 key=1;if(mode)key=1;//连续扫描按键if(key==1&&(KEY1==0||KEY2==0||KEY3==0||KEY4==0))//任意按键按下{delay_10us(1000);//消抖key=0;if(KEY1==0)return KEY1_PRESS;else if(KEY2==0)return KEY2_PRESS;else if(KEY3==0)return KEY3_PRESS;else if(KEY4==0)return KEY4_PRESS; }else if(KEY1==1&&KEY2==1&&KEY3==1&&KEY4==1) //无按键按下{key=1; }return KEY_UNPRESS;
}void main()
{ u8 key=0;u8 dir=0;//默认逆时针方向u8 speed=STEPMOTOR_MAXSPEED;//默认最大速度旋转u8 step=0;while(1){ key=key_scan(0);if(key==KEY1_PRESS)//换向{dir=!dir; }else if(key==KEY2_PRESS)//加速{if(speed>STEPMOTOR_MAXSPEED)speed-=1; }else if(key==KEY3_PRESS)//减速{if(speed<STEPMOTOR_MINSPEED)speed+=1; }step_motor_28BYJ48_send_pulse(step++,dir);if(step==8)step=0; delay_ms(speed); }
}
解析
总结
对单片机按键,led点阵,I/O口扩展,电机等进行了学习。
c51单片机学习笔记二相关推荐
- 【C51单片机学习笔记--DS1302时钟芯片蜂鸣器I2C总线AT24C02存储器】
C51单片机学习笔记–DS1302时钟芯片&&蜂鸣器&&I2C总线&&AT24C02存储器 文章目录 一.DS1302时钟芯片介绍 二.DS1302时钟 ...
- C51单片机学习笔记之定时器
简介 "定时器/计数器"说的是一个东西,因为它既能计时也能计数.是存在于单片机内部的一个独立的硬件部分,依赖晶振产生固定的时间间隔,产生了一定量的固定时间间隔后会引发定时器中断从而 ...
- c51单片机学习笔记-LED流水灯实验
目的:实现 LED 流水灯,只需循环让 D1-D8 指示灯逐个点亮. 方法:点亮 D1 且把 D2-D8 熄灭,延时一段时间后再点亮 D2 且把 D1. D3-D8 熄灭,延时一段时间后再点亮 D3 ...
- C51单片机学习笔记(一)——搭建开发环境及烧写工具
C51单片机学习笔记(一)--搭建开发环境及烧写工具 文章目录 C51单片机学习笔记(一)--搭建开发环境及烧写工具 1.搭建软件开发环境及使用(Keil uVision) 2.将程序下载到单片机(烧 ...
- 【C51单片机学习笔记----DS18B20温度传感器LCD1602液晶屏直流电机调速与呼吸灯AD模数转换红外外部中断】
文章目录 一.DS18B20温度传感器 1.DS18B20温度传感器连接原理图 2.DS18B20温度传感器单总线通信时序 3.DS18B20温度传感器代码模块 二.LCD1602液晶屏 1.LCD1 ...
- C51单片机学习笔记之串口通信
简介 串口通信就是单片机和pc之间的一种通信方式. 通信方式:并行,串行,同步,异步(最常用的) 传输方向:单工,半双工(不同时间),全双工 基本结构 相关寄存器 SCON串口控制寄存器(主要用方 ...
- C51单片机学习笔记之矩阵键盘
简介 矩阵键盘一般为4×4或4×3的.矩阵键盘的判断方式分按行扫描和按列扫描. 简单说就是给全体一个高电平,然后给一个按键的一端附上低电平,再判断另一端是否为低电平. 原理图 代码部分 #includ ...
- 51单片机学习笔记-1简介及点灯
51单片机学习笔记 文章目录 51单片机学习笔记 1. 51单片机简介 1.1 安装软件 1.2 单片机简介 2. LED灯 2.1点亮一个LED 2.1.1原理分析 2.1.2 创建工程 2.2LE ...
- ESP32 单片机学习笔记 - 06 - (以太网)Ethernet转Wifi
ESP32 单片机学习笔记 - 06 - (以太网)Ethernet转Wifi 暂停了半个多月的学习,去调车了.现在课设开始了,赶紧回来把一开始的"以太网"目标学完.但是却发现,好 ...
- AutoLeaders控制组—51单片机学习笔记
文章目录 AutoLeaders控制组-51单片机学习笔记 1.1单片机及开发板介绍 单片机介绍 单片机应用领域 STC89C52单片机 内部结构 开发板介绍 2.1点亮一个Led 新建工程 编程 认 ...
最新文章
- 转载:使用 OpenCV 识别 QRCode
- parcel react_如何使用Parcel捆绑React.js应用程序
- 二分类任务:确定一个人是否年收入超过5万美元
- Frost Sullivan权威报告:阿里云再次领跑云WAF大中华区市场
- ios5 ARC机制介绍和使用
- 双绞线传输距离_详细了解弱电工程最常用到的网络传输介质:同轴电缆、双绞线、光纤...
- linux学习查看日志命令
- 只要实现了annotation这个接口就是注解 同理:只要实现了某个接口就是该类型的实现类...
- java字典类_Java字典类
- python 生成嵌套字典
- JNI使用NewStringUTF崩溃的解决方法
- 各种电子元器件介绍与电路基础作用
- java程序设计-飞机大战
- 在 Windows 中为高级用户配置 IPv6 的指南
- UnblockNeteaseMusic解锁网易云灰色歌曲(更新:用咪咕音乐可以免费听)
- 【车牌识别】基于HOG特征提取和GRNN网络的车牌识别算法matlab仿真
- 用计算机算sin的按键顺序是什么,用计算器求sin50°的值,按键顺序是 [ ]A.B.C.D....
- 串口通信协议【I2C、SPI、UART、RS232、RS422、RS485、CAN、TTL、USB】
- 网站收录查询,常用的2种网站收录查询方法
- Android 安全分析和漏洞挖掘|工具集
热门文章
- c语言字符型常量的例题,C语言笔试题100道
- cmd命令根据wsdl文件生成Java文件
- scratch动态三角形拖动/自制素材/少儿编程scratch教研教案课件课程素材脚本
- JAVA中this的四种用法的详解
- linux(Ubuntu)下Navicat的激活与无限试用
- 移动边缘计算卸载技术笔记(一)
- c# 火狐浏览器怎么嵌入窗体中_.net winform程序下使用firefox作为Web浏览器
- Linux内核下载缓慢解决方法
- Octotree在GitHub中出错
- matlab 剔除toc,matlab-罗曼诺夫斯基准则剔除粗大值