51单片机学习总结(三)8*8点阵屏,串口通信(内含模块代码)

写博客的主要目的还是自己需要考试了,写在这里总结一番,如果给大家带来了帮助。鄙人不甚欢喜,如果有错误,欢迎大家指出

主控芯片

在这里插入图片描述

8*8点阵

原理图:
在这里插入图片描述
在这里插入图片描述(注:在51清翔单片机上面,这8个引脚是引出来,所以88使用的是这个原理图里面的1-6个引脚)
(注:清翔的点阵屏把需要使用的74HC595放到了点阵屏模块里面)
实物:
在这里插入图片描述在这里插入图片描述74HC595
因为点阵里面有8
8个LED灯,所以直接用串口去一个一个控制是不现实的,所以我们需要借助到595芯片。这一种芯片是一种串入并出的芯片,在电子显示屏里面被广泛的应用。其实质是串行输入/输出或者并行输出移位寄存器
芯片手册
在这里插入图片描述使用方法

SCLK和RCLK全部拉低到0
将需要输入的数据按照2进制压入一个
拉高SCLK
拉低SCLK

模块化代码

/*pbdata.h*/
#ifndef __PBDATA_H__
#define __PBDATA_H__
#define uchar unsigned  char
#define uint unsigned int

#include <reg52.h>
#include <intrins.h>
#include "Matrix.h"

/*8*8点阵*/
sbit DIO = P3^4;  //串行数据口
sbit S_CLK = P3^5;//移位寄存器时钟
sbit R_CLK = P3^6;//输出锁存器时钟

#endif
/*Matrix.h*/
#ifndef __MATRIX_H__
#define __MATRIX_H__


void Send_Byte(unsigned char dat);
void Display_DZ(uchar num);

#endif
/*Matrix.c*/
#include"pbdata.h"

/*点阵字形码*/
/*要显示的字符*/
unsigned char code tabel[2][8]={
0xE0,0xEE,0x01,0x6D,0x01,0x6D,0x01,0xEF,//"电"字符
0xE7,0xF7,0xF7,0xF7,0x80,0xF7,0xFB,0xC3//“子”字符
};

/*595发送一字节*/
void Send_Byte(unsigned char dat)
{
	unsigned char i; //循环次数变量
	S_CLK = 0;//拉低移位寄存器时钟
	R_CLK = 0;//拉低输出锁存器时钟
	for(i=0; i<8; i++) //循环8次
	{
		if(dat & 0x01)//发送1
			DIO = 1;
		else	  //发送0
			DIO = 0;
		dat >>= 1;//数据右移
		S_CLK = 1;//拉高移位寄存器时钟,数据移位
		S_CLK = 0;//拉低移位寄存器时钟
	}	
}

/*num表示需要输出的字符数字数量*/
void Display_DZ(uchar num)
{
	unsigned char j, k, ROW;//j发送8列和8行字形码,k字符数量,ROW行值
	unsigned int z;	//动态扫描延时变量
	while(1)
	{
		for(k=0; k<num; k++)//k 需要显示的字符数量
		{
			for(z=0; z<1000; z++)//z刷新次数
			{
				ROW = 0x80;//行选初值
				for(j=0; j<8; j++) //循环8次发送行和列值
				{
					Send_Byte(tabel[k][j]);//发送列选值
					Send_Byte(ROW);	//发送行选值
					R_CLK = 1; //拉高输出锁存器,把移位寄存器中数据输出
					R_CLK = 0; //拉低输出锁存器
					ROW = _cror_(ROW, 1);//右移,选择下一行	
				}
			}
		}
	}
}
/*main.c*/
#include "pbdata.h"

void main()
{
	while(1)
	{
		Display_DZ(2);
	}
}

(注:字符字形码根据自己的需要修改,有一个小软件可以直接求出来你需要显示的字形码的字符,可以私聊发)
(注:在更改了显示字符的时候,要注意改tabel和Display_DZ两个的参数)

串口通信

如果不想看原理 可以直接拉到最下面去看模块化代码,简单直接粗暴,更省时省心省力 😃
波特率
要学习串口通信,就一定要知道波特率,波特率就是每秒钟传输二进制代码的位数,单位是:位/秒(bps)
用一个简单的例子来讲解波特率,比如每秒钟传输240个字符,而每个字符的格式包含10位(1个起始位、1个停止位、8个数据位),这时候的比特率就是10位*240个/秒 = 2400 bsp
波特率的计算
在这里插入图片描述
在这里插入图片描述SMOD没配置的话默认为0
fosc是外部晶振 我们使用的是11.0592MHZ晶振
寄存器配置
因为通信需要中断,示意图在串行口工作之前必须要对相关寄存器进行配置,设定其工作模式。

设置T1工作方式 编辑TMOD寄存器
计算T1初值 装载TH1 TL1
启动T1 编辑TCON中的R1位
确定串行口控制 编辑SCON寄存器
如果需要串行口在中断下工作 在中断设置编程IE寄存器

数据手册
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述模块化代码

/*Uart.h*/
#ifndef __Uart_H__
#define __Uart_H__

void UartAction(unsigned char *buf, unsigned char len);
void ConfigUART(unsigned int baud);
void UartWrite(unsigned char *buf, unsigned char len);
unsigned char UartRead(unsigned char *buf, unsigned char len);
void UartRxMonitor(unsigned char ms);
void UartDriver();

#endif
/*Uart.c*/
#include <reg52.h>
#include <stdio.h>
#include <pbdata.h>
//存储数据到bufRxd[]数组里面,buf[]是另外一个存储谁都可以调用
//加上extern之后,不需要声明包含这个文件
#define uchar unsigned char 
#define uint unsigned int

bit flagFrame = 0; //帧接收完成标志,即接收到一帧新数据
bit flagTxd = 0; //单字节发送完成标志,用来替代TXD 中断标志位
unsigned char cntRxd = 0; //接收字节计数器
unsigned char pdata bufRxd[64]; //接收字节缓冲区 ,存储到RAM中

// 串口动作函数,用来添加自己需要的额外函数
void UartAction(unsigned char *buf, unsigned char len);

/* 串口配置函数,baud-通信波特率 */
void ConfigUART(unsigned int baud)
{
	EA = 1;			//打开总中断
	ES = 1; 		//打开串口中断
	SM0 = 0;SM1 = 1;	//串口工作方式1,8位UART波特率可变
	REN = 1;		//串口允许接收
	TR1 = 1;		//启动定时器1
	TMOD |= 0x20;		//定时器1,工作模式2 8位自动重装
	TH1=256-(11059200/12/32)/baud;
	TL1=TH1;
}
/* 串口数据写入,即串口发送函数,buf-待发送数据的指针,len-指定的发送长度 */
void UartWrite(unsigned char *buf, unsigned char len)
{
	while (len--) //循环发送所有字节
	{
		flagTxd = 0; //清零发送标志
		SBUF = *buf++; //发送一个字节数据,发送一个字节,然后指针后移
		while (!flagTxd); //等待该字节发送完成
	}
}
/*串口读取数据函数*/
unsigned char UartRead(unsigned char *buf, unsigned char len)
{
	unsigned char i;
	if (len > cntRxd) //指定读取长度大于实际接收到的数据长度时,
	{ //读取长度设置为实际接收到的数据长度
		len = cntRxd;
	}
	for (i=0; i<len; i++) //拷贝接收到的数据到接收指针上
	{
		*buf++ = bufRxd[i];//把发送到bufRxd上的数据存到buf上
	}
	cntRxd = 0; //接收计数器清零
	return len; //返回实际读取长度
}
/* 串口接收监控,由空闲时间判定帧结束,需在定时中断中调用,ms-定时间隔,一般1ms即可*/
void UartRxMonitor(unsigned char ms)
{
	static unsigned char cntbkp = 0;
	static unsigned char idletmr = 0;
	if (cntRxd > 0) //接收计数器大于零时,监控总线空闲时间
		{
		if (cntbkp != cntRxd) //接收计数器改变,即刚接收到数据时,清零空闲计时
		{
			cntbkp = cntRxd;//改变接收计数器
			idletmr = 0; //清0空闲计时
		}
		else //接收计数器未改变,即总线空闲时,累积空闲时间,判断是否接受完毕
		{
			if (idletmr < 30) //空闲计时小于30ms 时,持续累加
			{
				idletmr += ms;
				if (idletmr >= 30) //空闲时间达到30ms 时,即判定为一帧接收完毕
				{
					flagFrame = 1; //设置帧接收完成标志
				}
			}
		}
	}
		else
		{
			cntbkp = 0;
		}
}
/* 串口驱动函数,监测数据帧的接收,调度功能函数,需在主循环中调用 */
void UartDriver()
{
	unsigned char len;
	unsigned char pdata buf[40];
	if (flagFrame) //有命令到达时,读取处理该命令
	{
		flagFrame = 0;//改变状态为忙碌
		len = UartRead(buf, sizeof(buf)); //将接收到的命令读取到缓冲区中,并且放入buf中
		UartAction(buf, len); //传递数据帧,调用动作执行函数
	}
}
/* 串口中断服务函数 */
void InterruptUART() interrupt 4
{
	if (RI) //接收到新字节
	{
		RI = 0; //清零接收中断标志位
		if (cntRxd < sizeof(bufRxd)) //接收缓冲区尚未用完时,
		{ //保存接收字节,并递增计数器
			bufRxd[cntRxd++] = SBUF;
		}
	}
	if (TI) //字节发送完毕
	{
		TI = 0; //清零发送中断标志位
		flagTxd = 1; //设置字节发送完成标志
	}
}
  • 15
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

暮尘依旧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值