單片機:11章——12章筆記

第11章 UART串口通信

UART(Universal Asynchronous Receiver/Transmitter, 通用異步收發器)
波特率:baud,發送一位二進制數據的電平持續時間$ = \frac{1}{baud}$
在UART通信,規定:**當沒有通信信號發生時,通信線路保持高電平,當要發送數據之前,先一位0表示起始位,然後發送8位數據位,數據位是先低後高的順序,數據位發完後再發一位1表示停止位。

串口模塊的波特率發生器只能由定時器T1或定時器T2產生,而不能由定時器T0產生,默認是使用定時器1的模式2,定時器T1的重載值計算公式爲:TH1=TL1=256-晶振值/12/2/16/波特率
如果電源管理寄存器PCON的最高位=1,也就是如果PCON |=0x80;,計算公式就寫爲:TH1=TL1=256-晶振值/12/16/波特率;公式中的16重點說明,一位信號採集16次,取出第7、8、9次,如果這三次中有2次高電平,那麼就認爲是高電平,反之是低電平。
SBUF寄存器,地址:0x99

1. 利用定時器T0模擬串口通信程序

通過此程序能弄明白串口通信的原理

#include <reg52.h>

sbit TXD_PIN=P3^1;				//
sbit RXD_PIN=P3^0;				//
bit rxdOrTxd = 0;					//
bit rxdEnd = 0;						//
bit txdEnd = 0;						//
unsigned char rxdBuf=0;		//
unsigned char txdBuf=0;		//

void configUART(unsigned int baud);
void startTx(unsigned char dat);
void startRx(void);

void main()
{    
	EA=1;
	configUART(4800);
	while(1)
	{
		while(!RXD_PIN);  //
		startRx();
		while(!rxdEnd);
		startTx(rxdBuf+1);
		while(!txdEnd);
	}
}


/**
*  名稱:configUART
*  功能:T0中斷配置函數
*  參數:baud——串口波特率
**/
void configUART(unsigned int baud)
{
	unsigned int tmp;
	tmp=12000000/12/baud;   //256-TH0+(256-TH0)/2=
	TH0=256-tmp;
	TL0=TH0;
	TMOD &=0XF0;
	TMOD |=0x02;	
}

/**
*  名稱:
*  功能:啓動串口接收
*  參數:
**/
void startRx()
{
	TL0=256-((256-TH0)>>1);  //開始接收時,波特率減半,增大週期爲原來的2倍
	ET0=1;
	TR0=1;
	rxdOrTxd=0;
	rxdEnd=0;
}

/**
*  名稱:
*  功能:啓動串口發送
*  參數:dat——要發送的字節
**/
void startTx(unsigned char dat)
{
	txdBuf=dat;		//
	TL0=TH0;			//
	ET0=1;				//
	TR0=1;				//
	TXD_PIN=0;		//發送起始位0
	rxdOrTxd=1;		//
	txdEnd=0;			//
}

/**
*  功能:T0中斷服務函數,完成接收或發送數據的處理。
*  參數:無
**/
void timer0() interrupt 1
{
	static unsigned char cnt=0;
	if (rxdOrTxd)  //發送
	{
		cnt++;		//
		if (cnt <=8)
		{
			TXD_PIN =txdBuf & 0x01;
			txdBuf >>= 1;
		}
		else if (cnt == 9)
		{
			TXD_PIN=1;
		}
		else
		{
			TR0=0;
			ET0=0;
			cnt=0;
			txdEnd=1;
		}
	}
	else					//處理接收
	{
		if (cnt==0)
		{
			if (RXD_PIN)
			{
				TR0=0;
			}
			else
			{
				rxdBuf=0;
				cnt++;
			}
		}
		else if (cnt <=8)
		{
			rxdBuf >>=1;
			if(RXD_PIN)
			{
				rxdBuf |= 0x80;
			}
			cnt++;
		}
		else
		{
			TR0=0;
			cnt=0;
			if (RXD_PIN)
			{
				rxdEnd=1;
			}
		}
	}
}

2.串口演示例程

體驗指針和 sizeof()的用法。例程首先接收上位機下發的命令,根據命令值分別把不同數組的數據回發給上位機。在上位機串口調試助手中分別下發 1、2、3、4,就會得到不同的數組回發,注意這裏都用十六進制發送和十六進制顯示

#include <reg52.h>

bit cmdArrived=0;		//
unsigned char cmdIndex=0;	//
unsigned char cntTxd=0;		//
unsigned char *ptrTxd;		//

unsigned char a1[1]={1};
unsigned char a2[2]={1,2};
unsigned char a3[4]={1,2,3,4};
unsigned char a4[8]={1,2,3,4,5,6,7,8};

void configUART(unsigned int baud);

void main()
{    
	EA=1;
	configUART(4800);
	while(1)
	{
		if (cmdArrived)
		{
			cmdArrived=0;
			switch(cmdIndex)
			{
				case(1): ptrTxd = a1; cntTxd=sizeof(a1);TI=1;break;
				case(2): ptrTxd = a2; cntTxd=sizeof(a2);TI=1;break;
				case(3): ptrTxd = a3; cntTxd=sizeof(a3);TI=1;break;
				case(4): ptrTxd = a4; cntTxd=sizeof(a4);TI=1;break;
				default: break;
			}
		}
	}
}

/**
*  名稱:configUART
*  功能:T1中斷配置函數
*  參數:baud——串口波特率
**/
void configUART(unsigned int baud)
{
	unsigned int tmp;
	SCON=0X50;										//配置串口爲模式1
	TMOD &=0X0F;									//
	TMOD |=0x20;
	tmp=12000000/12/2/16/baud; 		//
	TH1=256-tmp;
	TL1=TH0;											//
	ET1=0;	
	ES=1;													//使能串口中斷
	TR1=1;
}

/**
*  功能:串口中斷服務函數,完成接收或發送數據的處理。
*  參數:無
**/
void UART() interrupt 4
{
	if(RI)
	{
		RI=0;
		cmdIndex=SBUF;
		cmdArrived=1;
	}
	if (TI)
	{
		
		TI=0;
		if (cntTxd>0)
		{
			SBUF=*ptrTxd;
			cntTxd=0;
			ptrTxd++;
		}
	}
}

第12章 指針基礎與1602認識

sizeof()操作,相當於一個常量,因它是在程序編譯的時候進行的,sizeof()括號中可以是變量名,也可以是變量類型名

  • 常量:直接常量與符號常量
    符號常量聲明的兩種方式:
    : const 類型 符號常量名字 = 常量值;
    : #define 符號常量名 常量值
    字符型常量有兩種,普通字符和轉義字符
    字符串常量在內存中按順序逐個存儲字符串中的字符的ASCII碼值,最後有一個字符’\0’

單片機讀外部狀態前,必須先保證自己是高電平

1602操作時序

#define LCD1602_DB P0
sbit LCD1602_RS = P1^0;
sbit LCD1602_RW = P1^1;
sbit LCD1602_E = P1^5;

  1. 讀狀態:RS=L, R/W=H, E=H;
LCD1602_DB = 0XFF;
LCD1602_RS=0;
LCD1602_RW=1;
LCD1602_E=1;
sta = LCD1602_DB;

如果1602設備處於忙的狀態,需要等待;由於P0總線被多個設備共用,因此需及時釋放P0總線,避免干擾其它設備的使用。因此改寫上面程序:

LCD1602_DB=0xFF;
LCD1602_RS=0;
LCD1602_RW=1;
do {
    LCD1602_E=1;
    sta=LCD1602_DB;
    LCD1602_E=0;
} while(sta & 0x80)
  1. 讀數據:RS=H, R/W=L,E=H;

  2. 寫指令:RS=L, R/W=L, D0~D7=指令碼, E=高脈衝;
    E=高脈衝的意思就是:E使能引腳先從低拉高,再從高拉低,形成一個高脈衝。

  3. 寫數據:RS=H, R/W=L, D0~D7=指令碼, E=高脈衝;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章