零、引脚
- 0 宏定义数码管段码口 点阵列控制端口
- 1 右下角矩阵按键控制口
- 1.0 直流电机控制管脚
- 1.0 1.1 1.2 1.3 控制步进电机管脚
- 2.0 右边的LED
- 2.1 SCL时钟线 2.0 SDA数据线
- 2.2 2.3 2.4 左上角的数码管
- 2.5 蜂鸣器
- 3.1 3.0 3.2 3.3 左下角的四个独立按键控制脚
- 3.4 串行数据输入
- 3.5 存储寄存器时钟输入
- 3.6 移位寄存器时钟输入
一、跑马灯
/*单个灯闪烁
LED1=0; //点亮
delay_10us(50000); //大约延时 4500ms
LED1=1; //熄灭
delay_10us(50000);
*/
/*跑马灯
u8 i;
for (i = 0; i < 8; i ++)
{
LED_PORT = ~(0x01 << i);
delay_10us(50000);
}
*/
/*循环跑马灯
for (i = 1; i < 8; i ++)
{
LED_PORT = _crol_(LED_PORT, 1);
delay_10us();
}
for (i = 1; i < 8; i ++)
{
LED_PORT = _cror_(LED_PORT, 1);
delay_10us();
}
*/
二、蜂鸣
原理:该蜂鸣器是无源的,加上扰动才能发音。
一定要在外面加上while(1),但原因不知道。
while (i --){
BEEP = !BEEP;
delay_10us();
}
i = 0;
三、静态显示
将a~小数点的01写出来后反过来 最顶的是a 他右边的是b 转个圈
只能显示最左边的一个位置
如1000 0111
计算时为 1110 1000
为 e1
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iolf02To-1655964413878)(https://i.bmp.ovh/imgs/2022/06/20/3b17585168ab885f.png)]
#include "reg52.h"
//#include "intrins.h"
//#define LED_PORT P2 //使用宏定义 LED灯
#define SMG_A_DP_PORT P0 //使用宏定义数码管段码口 左上角的第0个
//sbit LED1=P2^7;
//sbit BEEP=P2^5; //将 P2.5 管脚定义为 BEE 蜂鸣器
typedef unsigned int u16; //对系统默认数据类型进行重命名
typedef unsigned char u8;
void delay_10us()
{
u16 ten_us = 50000;
while(ten_us--);
}
void main(){
//共阴极数码管显示 0~F 的段码数据
//将a~小数点的01写出来后反过来
u8 gsmg_code[17] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
u16 i;
for (i = 0; i < 16; i ++)
{
SMG_A_DP_PORT = gsmg_code[i];//将数组第 1 个数据赋值给数码管段选口
delay_10us();
}
while (1)
{
}
}
四、动态数码管
似乎只能把三个引脚设为2.2、2.3、2.4
理解成三个引脚合成一个位置。
ABC是234,写的时候以CBA来看。如此时C=0; B=0; A = 1
,那么他表示的是从右到左第1个位置。
实现从右往左跑马灯“HELLO WORLD”
/**************************************************************************************
深圳市普中科技有限公司(PRECHIN 普中)
技术支持:www.prechin.net
实验名称:动态数码管实验
接线说明:
实验现象:下载程序后“数码管模块”显示01234567
注意事项:
***************************************************************************************/
#include "reg52.h"
typedef unsigned int u16; //对系统默认数据类型进行重定义
typedef unsigned char u8;
#define SMG_A_DP_PORT P0 //使用宏定义数码管段码口
//定义数码管位选信号控制脚
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
//HELLO WORLD
u8 gsmg_code[17]={0x76, 0x79, 0x38, 0x38, 0x3f, 0x00, 0x3c, 0x1e, 0x3f, 0x50, 0x38, 0x5e, 0x00, 0x00}; //14
/*******************************************************************************
* 函 数 名 : delay_10us
* 函数功能 : 延时函数,ten_us=1时,大约延时10us
* 输 入 : ten_us
* 输 出 : 无
*******************************************************************************/
void delay_10us(u16 ten_us)
{
while(ten_us--);
}
/*******************************************************************************
* 函 数 名 : smg_display
* 函数功能 : 动态数码管显示
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void smg_display(void)
{
u8 i = 0;
u8 t, k, j;
u8 show_code[8];
//HELLO WOrLd 从右到左
while (1){
i = (i) % 14; //将要加进来的输出数组下标
for (k = 0; k < 7; k ++) show_code[k] = show_code[k + 1];
show_code[7] = gsmg_code[i ++];
//每次输出一个长度为8的数组
t = 100;
while (t --)
{
for (j = 0; j < 8; j ++)
{
switch(j)//位选
{
case 0: LSC=1;LSB=1;LSA=1;break;
case 1: LSC=1;LSB=1;LSA=0;break;
case 2: LSC=1;LSB=0;LSA=1;break;
case 3: LSC=1;LSB=0;LSA=0;break;
case 4: LSC=0;LSB=1;LSA=1;break;
case 5: LSC=0;LSB=1;LSA=0;break;
case 6: LSC=0;LSB=0;LSA=1;break;
case 7: LSC=0;LSB=0;LSA=0;break;
}
SMG_A_DP_PORT=show_code[j];//传送段选数据
delay_10us(100);//延时一段时间,等待显示稳定
SMG_A_DP_PORT=0x00;//消音
}
}
delay_10us(100);
}
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{
while(1)
{
smg_display();
}
}
五、独立按键
按键被按时被按的变为0,电流变化是输入
/**************************************************************************************
深圳市普中科技有限公司(PRECHIN 普中)
技术支持:www.prechin.net
实验名称:独立按键实验
接线说明:
实验现象:下载程序后,按下“独立按键”模块中K1键,控制D1指示灯亮灭
注意事项:
***************************************************************************************/
#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 0
/*******************************************************************************
* 函 数 名 : delay_10us
* 函数功能 : 延时函数,ten_us=1时,大约延时10us
* 输 入 : ten_us
* 输 出 : 无
*******************************************************************************/
void delay_10us(u16 ten_us)
{
while(ten_us--);
}
/*******************************************************************************
* 函 数 名 : key_scan
* 函数功能 : 检测独立按键是否按下,按下则返回对应键值
* 输 入 : mode=0:单次扫描按键
mode=1:连续扫描按键
* 输 出 : KEY1_PRESS:K1按下
KEY2_PRESS:K2按下
KEY3_PRESS:K3按下
KEY4_PRESS:K4按下
KEY_UNPRESS:未有按键按下
*******************************************************************************/
u8 key_scan(u8 mode)
{
static u8 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;
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{
u8 key=0;
while(1)
{
key=key_scan(0);
if(key==KEY1_PRESS)//检测按键K1是否按下
LED1=!LED1;//LED1状态翻转
}
}
六、矩阵按键
8个I/O口,4行4列
先行后列,从左往右分别代表1234
每加一行加4,结果加列。0表示被按下。
/**************************************************************************************
深圳市普中科技有限公司(PRECHIN 普中)
技术支持:www.prechin.net
实验名称:矩阵按键实验
接线说明:
实验现象:下载程序后,按下“矩阵按键”模块中S1-S16键,对应数码管最左边显示0-F
注意事项:
***************************************************************************************/
#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 };
/*******************************************************************************
* 函 数 名 : delay_10us
* 函数功能 : 延时函数,ten_us=1时,大约延时10us
* 输 入 : ten_us
* 输 出 : 无
*******************************************************************************/
void delay_10us(u16 ten_us)
{
while (ten_us--);
}
/*******************************************************************************
* 函 数 名 : key_matrix_flip_scan
* 函数功能 : 使用线翻转扫描方法,检测矩阵按键是否按下,按下则返回对应键值
* 输 入 : 无
* 输 出 : key_value:1-16,对应S1-S16键,
0:按键未按下
*******************************************************************************/
u8 key_matrix_flip_scan(void)
{
static u8 key_value = 0;
KEY_MATRIX_PORT = 0x0f;//给所有行赋值0,列全为1
if (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);//等待按键松开
}
}
else
key_value = 0;
return key_value;
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{
u8 key = 0;
while (1)
{
key = key_matrix_flip_scan();
if (key != 0)
SMG_A_DP_PORT = gsmg_code[key - 1];//得到的按键值减1换算成数组下标对应0-F段码
}
}
七、IO 扩展
右上角的点阵
u8 ghc595_buf[8]={0x01,0x02,0x03,0x0f,0x10,0x20,0x40,0x80};
最下面是0000 0001(0x01),最上面是1000 0000(0x80)
移位寄存器 -> 存储寄存器 传东西
如果两个时钟连在一起,则移位寄存器总是比存储器早一个脉冲
for 循环里面最好不要有等于。可能是精度问题。
将LED点阵列全部设置为0,即LED阴极为低电平,当有1时亮灯。
将移位寄存器和存储器置0置1表示传输数据。
/**************************************************************************************
深圳市普中科技有限公司(PRECHIN 普中)
技术支持:www.prechin.net
实验名称:IO扩展(串转并)实验-74HC595
接线说明:
实验现象:下载程序后,8*8LED点阵以一行循环滚动显示
注意事项:LED点阵旁的J24黄色跳线帽短接到GND一端
***************************************************************************************/
#include "reg52.h"
typedef unsigned int u16; //对系统默认数据类型进行重定义
typedef unsigned char u8;
//定义74HC595控制管脚
sbit SRCLK=P3^6; //移位寄存器时钟输入
sbit RRCLK=P3^5; //存储寄存器时钟输入
sbit SER=P3^4; //串行数据输入
#define LEDDZ_COL_PORT P0 //点阵列控制端口
u8 ghc595_buf[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
/*******************************************************************************
* 函 数 名 : delay_10us
* 函数功能 : 延时函数,ten_us=1时,大约延时10us
* 输 入 : ten_us
* 输 出 : 无
*******************************************************************************/
void delay_10us(u16 ten_us)
{
while(ten_us--);
}
/*******************************************************************************
* 函 数 名 : delay_ms
* 函数功能 : ms延时函数,ms=1时,大约延时1ms
* 输 入 : ten_us
* 输 出 : 无
*******************************************************************************/
void delay_ms(u16 ms)
{
u16 i,j;
for(i=ms;i>0;i--)
for(j=110;j>0;j--);
}
/*******************************************************************************
* 函 数 名 : hc595_write_data(u8 dat)
* 函数功能 : 向74HC595写入一个字节的数据
* 输 入 : dat:数据
* 输 出 : 无
*******************************************************************************/
void hc595_write_data(u8 dat)
{
u16 i;
//不能在大循环里写上大于等于 推测精度原因
for(i = 8; i > 0; i--)//循环8次即可将一个字节写入寄存器中
{
SER = (dat >> (i - 1)) & 1;//优先传输一个字节中的高位
// dat <<= 1;//将低位移动到高位
SRCLK=0;
delay_10us(1);
SRCLK=1;
delay_10us(1);//移位寄存器时钟上升沿将端口数据送入寄存器中
}
RRCLK=0;
delay_10us(1);
RRCLK=1;//存储寄存器时钟上升沿将前面写入到寄存器的数据输出
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
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 点阵实验
8.1 点灯
LEDDZ_COL_PORT=0x00;
设置的是列数。当列数为0时可被点亮、当列数为1时不能被点亮。
/**************************************************************************************
深圳市普中科技有限公司(PRECHIN 普中)
技术支持:www.prechin.net
实验名称:LED点阵实验(点亮一个点)
接线说明:
实验现象:下载程序后,8*8LED点阵点亮左上角第一个点
注意事项:LED点阵旁的J24黄色跳线帽短接到GND一端
***************************************************************************************/
#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 //点阵列控制端口
/*******************************************************************************
* 函 数 名 : delay_10us
* 函数功能 : 延时函数,ten_us=1时,大约延时10us
* 输 入 : ten_us
* 输 出 : 无
*******************************************************************************/
void delay_10us(u16 ten_us)
{
while (ten_us--);
}
/*******************************************************************************
* 函 数 名 : hc595_write_data(u8 dat)
* 函数功能 : 向74HC595写入一个字节的数据
* 输 入 : dat:数据
* 输 出 : 无
*******************************************************************************/
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;//存储寄存器时钟上升沿将前面写入到寄存器的数据输出
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{
u8 i = 0;
LEDDZ_COL_PORT = 0x7f;//将LED点阵左边第一列设置为0,即LED阴极为低电平,其余列为1,即高电平
while (1)
{
hc595_write_data(0x87); //行
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/b866405c79bb99fda9afba47411034bf.jpeg)
8.2 显示数字、图形
每次亮一列,每列的哪几行看着亮。
/**************************************************************************************
深圳市普中科技有限公司(PRECHIN 普中)
技术支持:www.prechin.net
实验名称:LED点阵实验(显示数字)
接线说明:
实验现象:下载程序后,8*8LED点阵显示数字0
注意事项:LED点阵旁的J24黄色跳线帽短接到GND一端
***************************************************************************************/
#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 gled_row[8]={0x20,0x7F,0x80,0x49,0x7F,0x49,0x4F,0x01};//LED点阵显示数字0的行数据
u8 gled_col[8]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};//LED点阵显示数字0的列数据
/*******************************************************************************
* 函 数 名 : delay_10us
* 函数功能 : 延时函数,ten_us=1时,大约延时10us
* 输 入 : ten_us
* 输 出 : 无
*******************************************************************************/
void delay_10us(u16 ten_us)
{
while(ten_us--);
}
/*******************************************************************************
* 函 数 名 : hc595_write_data(u8 dat)
* 函数功能 : 向74HC595写入一个字节的数据
* 输 入 : dat:数据
* 输 出 : 无
*******************************************************************************/
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;//存储寄存器时钟上升沿将前面写入到寄存器的数据输出
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
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);//消影
}
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/49c65f06409e414a9c8433027641f11a.jpeg)
/**************************************************************************************
深圳市普中科技有限公司(PRECHIN 普中)
技术支持:www.prechin.net
实验名称:LED点阵实验(显示数字)
接线说明:
实验现象:下载程序后,8*8LED点阵显示数字0
注意事项:LED点阵旁的J24黄色跳线帽短接到GND一端
***************************************************************************************/
#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 gled_row[7][8]={{0x38,0x7C,0x7E,0x3F,0x1F,0x7E,0x7C,0x38},
{0x00,0x18,0x3C,0x1E,0x1E,0x3C,0x18,0x00},
{0x38,0x7C,0x7E,0x3F,0x1F,0x7E,0x7C,0x38},
{0x00,0x18,0x3C,0x1E,0x1E,0x3C,0x18,0x00},
{0x10,0x10,0x10,0x10,0x10,0x54,0x38,0x10},
{0x60,0xF0,0x7C,0x7E,0xFF,0x6F,0x1E,0x0C},
{0x60,0xF0,0x7C,0x7E,0xFF,0x6F,0x1E,0x0C},
};//LED点阵显示数字0的行数据
u8 gled_col[8]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};//LED点阵显示数字0的列数据
/*******************************************************************************
* 函 数 名 : delay_10us
* 函数功能 : 延时函数,ten_us=1时,大约延时10us
* 输 入 : ten_us
* 输 出 : 无
*******************************************************************************/
void delay_10us(u16 ten_us)
{
while(ten_us--);
}
/*******************************************************************************
* 函 数 名 : hc595_write_data(u8 dat)
* 函数功能 : 向74HC595写入一个字节的数据
* 输 入 : dat:数据
* 输 出 : 无
*******************************************************************************/
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;//存储寄存器时钟上升沿将前面写入到寄存器的数据输出
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{
u8 i=0, j=0, k=0;
while(1)
{
for (j = 0; j < 7; j ++)
{
k = 50;
while (k --)
{
for(i=0;i<8;i++)//循环8次扫描8行、列
{
LEDDZ_COL_PORT=gled_col[i];//传送列选数据
hc595_write_data(gled_row[j][i]);//传送行选数据
delay_10us(100);//延时一段时间,等待显示稳定
hc595_write_data(0x00);//消影
}
}
delay_10us(1000);
}
}
}
九、直流电机
/**************************************************************************************
深圳市普中科技有限公司(PRECHIN 普中)
技术支持:www.prechin.net
实验名称:直流电机实验
接线说明:
实验现象:下载程序后,直流电机旋转5S后停止
注意事项:将直流电机两根线分别连接到“步进电机模块”输出端子J47的5V和O1上。
***************************************************************************************/
#include "reg52.h"
typedef unsigned int u16; //对系统默认数据类型进行重定义
typedef unsigned char u8;
//定义直流电机控制管脚
sbit DC_Motor=P1^0;
#define DC_MOTOR_RUN_TIME 5000 //定义直流电机运行时间为5000ms
/*******************************************************************************
* 函 数 名 : delay_ms
* 函数功能 : ms延时函数,ms=1时,大约延时1ms
* 输 入 : ms:ms延时时间
* 输 出 : 无
*******************************************************************************/
void delay_ms(u16 ms)
{
u16 i,j;
for(i=ms;i>0;i--)
for(j=110;j>0;j--);
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{
DC_Motor=1;//开启电机
delay_ms(DC_MOTOR_RUN_TIME);
DC_Motor=0;//关闭电机
while(1)
{
}
}
十、步进电机
控制速度的方法:停止等待。
五条线:1条总电源,4条控制磁。
A->AB->B->BC->C->CD->D->DA 转子每次只走半步 45 度,所以 这也被称为半步驱动,与整步相比半步的旋转方式旋转起来更加的顺滑。
A->B->C->D 也能走,但是当休眠时间很短时就走不动了(该情况下8个分支的还能走)。
/**************************************************************************************
深圳市普中科技有限公司(PRECHIN 普中)
技术支持:www.prechin.net
实验名称:步进电机实验
接线说明:
实验现象:下载程序后,当按下KEY1键可调节电机旋转方向;当按下KEY2键,电机加速;
当按下KEY3键,电机减速
注意事项:将步进电机红色线对接到“步进电机模块”输出端子J47的5V上,其它相序依次接入。
***************************************************************************************/
#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
/*******************************************************************************
* 函 数 名 : delay_10us
* 函数功能 : 延时函数,ten_us=1时,大约延时10us
* 输 入 : ten_us
* 输 出 : 无
*******************************************************************************/
void delay_10us(u16 ten_us)
{
while(ten_us--);
}
/*******************************************************************************
* 函 数 名 : delay_ms
* 函数功能 : ms延时函数,ms=1时,大约延时1ms
* 输 入 : ten_us
* 输 出 : 无
*******************************************************************************/
void delay_ms(u16 ms)
{
u16 i,j;
for(i=ms;i>0;i--)
for(j=110;j>0;j--);
}
/*******************************************************************************
* 函 数 名 : step_motor_28BYJ48_send_pulse
* 函数功能 : 输出一个数据给ULN2003从而实现向步进电机发送一个脉冲
* 输 入 : step:指定步进序号,可选值0~7
dir:方向选择,1:顺时针,0:逆时针
* 输 出 : 无
*******************************************************************************/
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;//停止相序
}
}
/*******************************************************************************
* 函 数 名 : key_scan
* 函数功能 : 检测独立按键是否按下,按下则返回对应键值
* 输 入 : mode=0:单次扫描按键
mode=1:连续扫描按键
* 输 出 : KEY1_PRESS:K1按下
KEY2_PRESS:K2按下
KEY3_PRESS:K3按下
KEY4_PRESS:K4按下
KEY_UNPRESS:未有按键按下
*******************************************************************************/
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;
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
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);
}
}
十一、中断
有点像操作系统里面的0x80
11.1 外部中断(按键)
通常我们 都是使用基本的 2 个外部中断:INT0 和 INT1
INT0 对应的是 P3.2 口的附加功能;INT1 对应的是 P3.3 口的附加功能。
可由 IT0(TCON.0)选择其为低电平有 效还是下降沿有效。当 CPU 检测到 P3.2 引脚上出现有效的中断信号时,中断标 志 IE0(TCON.1)置 1,向 CPU 申请中断。
下降沿:被按下
这里有时红灯一闪一闪,原因:红外接收传感器与 K3 共用 P3.2 口。使用红外线遥控器同样可以开关。
/**************************************************************************************
深圳市普中科技有限公司(PRECHIN 普中)
技术支持:www.prechin.net
实验名称:外部中断0实验
接线说明:
实验现象:下载程序后,当按下K3键可控制D1指示灯亮灭
注意事项:将红外接收传感器取下,防止对P3.2口干扰
***************************************************************************************/
#include "reg52.h"
typedef unsigned int u16; //对系统默认数据类型进行重定义
typedef unsigned char u8;
//定义LED1管脚
sbit LED1=P2^0;
//定义独立按键K3控制脚
sbit KEY3=P3^2;
/*******************************************************************************
* 函 数 名 : delay_10us
* 函数功能 : 延时函数,ten_us=1时,大约延时10us
* 输 入 : ten_us
* 输 出 : 无
*******************************************************************************/
void delay_10us(u16 ten_us)
{
while(ten_us--);
}
/*******************************************************************************
* 函 数 名 : exti0_init
* 函数功能 : 外部中断0配置函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void exti0_init(void)
{
IT0=1;//跳变沿触发方式(下降沿)
EX0=1;//打开INT0的中断允许
EA=1;//打开总中断
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{
exti0_init();//外部中断0配置
while(1)
{
}
}
void exti0() interrupt 0 //外部中断0中断函数
{
delay_10us(1000);//消斗
if(KEY3==0)//再次判断K3键是否按下
LED1=!LED1;//LED1状态翻转
}
11.2 定时器中断
工作方式 | 图片 |
---|---|
方式0 | ![]() |
方式1 | ![]() |
方式2 | ![]() |
方式3 | ![]() |
51 系列单片机一定有基本的 2 个定时器 (定时器 0 和定时器 1),但不全有 3 个中断,通常我们使 用的是基本的 2 个定时器:定时器 0/1。
常用的是方式1:总体上是TH0和TL0组成一个数字(各8位)做自增,当这个数字自增到溢出时发生一次中断。
/**************************************************************************************
深圳市普中科技有限公司(PRECHIN 普中)
技术支持:www.prechin.net
实验名称:定时器0实验
接线说明:
实验现象:下载程序后,D1指示灯间隔1s闪烁
注意事项:
***************************************************************************************/
#include "reg52.h"
typedef unsigned int u16; //对系统默认数据类型进行重定义
typedef unsigned char u8;
//定义LED1管脚
sbit LED1=P2^0;
/*******************************************************************************
* 函 数 名 : delay_10us
* 函数功能 : 延时函数,ten_us=1时,大约延时10us
* 输 入 : ten_us
* 输 出 : 无
*******************************************************************************/
void delay_10us(u16 ten_us)
{
while(ten_us--);
}
/*******************************************************************************
* 函 数 名 : time0_init
* 函数功能 : 定时器0中断配置函数,通过设置TH和TL即可确定定时时间
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void time0_init(void)
{
TMOD|=0X01;//选择为定时器0模式,工作方式1
TH0=0XFC; //给定时器赋初值,定时1ms
TL0=0X18;
ET0=1;//打开定时器0中断允许
EA=1;//打开总中断
TR0=1;//打开定时器
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{
time0_init();//定时器0中断配置
while(1)
{
}
}
void time0() interrupt 1 //定时器0中断函数
{
static u16 i;//定义静态变量i
TH0=0XFC; //给定时器赋初值,定时1ms
TL0=0X18;
i++;
if(i==1000)
{
i=0;
LED1=!LED1;
}
}
十二、串口通信
实验软件的波特率要和程序里写的波特率一样。
RS232 的通信协议比较简单,通常遵循 96-N-8-1 格式。 “96”表示的是通信波特率为 9600。串口通信中通常使用的是异步串口通 信,即没有时钟线,所以两个设备要通信,必须要保持一致的波特率。
如果使用黄色跳线帽将 P5 端子的 1、2 短接,3、4 短接,那么 CH340 串口与 单片机串口是连接一起的,此时即可实现程序的下载或串口通信。
/**************************************************************************************
深圳市普中科技有限公司(PRECHIN 普中)
技术支持:www.prechin.net
实验名称:串口通信实验
接线说明:
实验现象:下载程序后,当串口助手发送数据给单片机,单片机原封不动转发给串口助手显示
注意事项:使用黄色跳线帽将CH340旁的P5端子的UTX和P30短接,URX和P31短接,出厂默认已短接好
***************************************************************************************/
#include "reg52.h"
typedef unsigned int u16; //对系统默认数据类型进行重定义
typedef unsigned char u8;
/*******************************************************************************
* 函 数 名 : uart_init
* 函数功能 : 串口通信中断配置函数,通过设置TH和TL即可确定定时时间
* 输 入 : baud:波特率对应的TH、TL装载值
* 输 出 : 无
*******************************************************************************/
void uart_init(u8 baud)
{
TMOD|=0X20; //设置计数器工作方式2
SCON=0X50; //设置为工作方式1
PCON=0X80; //波特率加倍
TH1=baud; //计数器初始值设置
TL1=baud;
ES=1; //打开接收中断
EA=1; //打开总中断
TR1=1; //打开计数器
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{
uart_init(0XFA);//波特率为9600
while(1)
{
}
}
void uart() interrupt 4 //串口通信中断函数
{
u16 rec_data;
RI = 0; //清除接收中断标志位
rec_data=SBUF; //存储接收到的数据
SBUF=rec_data; //将接收到的数据放入到发送寄存器
while(!TI); //等待发送数据完成
TI=0; //清除发送完成标志位
}
传入再传出。尝试了下加法,效果步理想。
十三、I2C-EEPROM 实验
只能说这个实验只能勉强理解在干啥。
13.1 项目总览
从这里开始不再是一个光.c
文件了。
照着教程配了下文件。下载时记得要换文件路径了。
程序由以下几个功能实现:
功能名称 | 功能 |
---|---|
key | 按键检测 |
smg | 数码管显示 |
iic | I2C 读写字节 |
24c02 | AT24C02 读写字节 |
13.2 通信协议
模拟I2C时序,实现与 AT24C02(EEPROM)之间的双向通信。
13.2.1 I2C
SCL时钟线 SDA数据线
一个 I2C 总线只使用两条总线线路,一条双向串行数据线(SDA),一 条串行时钟线(SCL)。数据线即用来表示数据,时钟线用于数据收发同步。
总线通过上拉电阻接到电源。当 I2C 设备空闲时,会输出高阻态,而 当所有设备都空闲,都输出高阻态时,由上拉电阻把总线拉成高电平。
应答:低电平脉冲
非应答:高电平脉冲
13.2.2 AT24C02
根据iic协议实现传输
13.3 小结
模拟的iic协议。大概能理解意思,没太懂这个实验的细节。
十四、DS18B20 温度传感器实验
用传感器采集数据后显示出来,重点在于处理采集到的数据。
传输数据等操作时必须要有拉低DQ后DQ=1的操作。按照硬件的操作要求来。
十五、小结
之后的实验似乎都是连接外设,根据外设的硬件规范编写相应的连接函数再操作,这里就不再写了。
我觉得单片机和平时接触到的不同点在于:它是和硬件一同完成功能的。硬件提供接口,程序捕捉或改变接口的电气性质完成操作。
对电脑是怎样跑起来的多了点儿理解。