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; //設置字節發送完成標誌
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章