久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

專注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機(jī)教程網(wǎng) >> MCU設(shè)計(jì)實(shí)例 >> 瀏覽文章

使用51的定時(shí)器模擬串口

作者:佚名   來源:本站原創(chuàng)   點(diǎn)擊數(shù):  更新時(shí)間:2012年08月25日   【字體:

  對(duì)于一部分坑爹的51單片機(jī)來說,壓根就米有串口啊!!特別是用來做小東西的利器:STC15F100系列的,坑爹到串口都米有的地步。當(dāng)然,我們可以使用軟件來模擬串口。可惜,軟件模擬的串口速度那個(gè)慢(12T單片機(jī)),誤碼率比硬件串口那個(gè)高……但是總比沒有的好。這個(gè)玩意不像硬件一樣能支持全雙工(12T的。1T的可以,畢竟12T的定時(shí)器中斷頻率快了主程序直接會(huì)被阻塞了……)。

另外STC的手冊(cè)上面說的8位自動(dòng)重載定時(shí)器竟然TMOD等于6!導(dǎo)致我搞了一下午都調(diào)不通,沒想到老妖寫錯(cuò)了……定時(shí)器重載模式應(yīng)該是=2.我現(xiàn)在想把TMOD寄存器的O去掉,再用這個(gè)詞問候他們?nèi)遥。?/p>

順便說一句,1T的51單片機(jī)足夠在定時(shí)器里實(shí)現(xiàn)全雙工,這就是為什么老妖說真實(shí)波特率要/3的原因。有RCNT=3這個(gè)語句在,所以可以實(shí)現(xiàn)同時(shí)接收發(fā)送……老妖寫程序不寫注釋是出了名的……但是至于普通的12T單片機(jī)。如果也用老妖得的程序,要注意定時(shí)器模式?jīng)]有16位自動(dòng)重裝模式。如果/3的話,9600就成3200的波特率了……還是非標(biāo)準(zhǔn)的,這個(gè)程序在89C52上最高波特率只能到9600,繼續(xù)往上加就嚴(yán)重誤碼……所以模擬串口還是用1T單片機(jī)或者12T降3倍速吧,(但是速度能卡的可怕,我感覺9600都卡)。要不然誤碼率能搞死人。

對(duì)了,順便說明一下,這個(gè)程序在keil c51上通不過,因?yàn)镵eil內(nèi)置putchar……會(huì)提示重復(fù)定義。能過keil的程序請(qǐng)參考 http://www.zg4o1577.cn/mcu/1541.html, 而且似乎keil的printf函數(shù)有毛病……

#include <hwconfig.h>
#include <type-def.h>
#include <stdio.h>


void WaitTF0()
{
	while(!TF0);
	TF0=0;
}

void WByte(BYTE out)
{
    //發(fā)送啟始位
    BYTE i=8;
    BYTE tmp=out;
    TR0=1;//開定時(shí)器
    TX1=0;
    WaitTF0();
    //發(fā)送8位數(shù)據(jù)位
    while(i--)
    {
        TX1=(tmp&0x01);     //先傳低位
        tmp=tmp>>1;
        WaitTF0();
    }
    //發(fā)送校驗(yàn)位(無)
    //發(fā)送結(jié)束位
    TX1=1;
    WaitTF0();
    TR0=0;
}    
void putchar(char ch)
{
	WByte(ch);
}
BYTE RByte()
{
	BYTE in=0;
	BYTE cnt;
	while(RX1==1);//等待RXD變低,啟動(dòng)定時(shí)器,這個(gè)是阻塞模式
	TR0=1;//同步開定時(shí)器
	WaitTF0();//等到周期過去
	for(cnt=0;cnt<8;cnt++)
	{
		in=in >>1;//從高移到低
		if(RX1==1) in = in | 0x80;//如果RXD=1,則最高置位
		WaitTF0();//等待一位過去
	}
	//等待停止位
	//WaitTF0();
	TR0=0;//關(guān)閉定時(shí)器
	return in;
}

void Init_VSer()
{
	//指令周期=(1000000/Baud)/(12/SysClock)
	//定時(shí)器值=0x100-指令周期
    TMOD |=0x02;  //計(jì)數(shù)器0,方式2
	TH0=0xa0;                    
    TL0=0xa0;        
    TR0=0;       //停止計(jì)數(shù)
    //TF0=0;	
	//ET0=0;		//T1中斷關(guān)
	//EA=0;		//總中斷關(guān)
}


void main()
{
	BYTE a;
	Init_VSer();
	printf("Hello,world!\n");
	while(1)
	{
		a=RByte();//阻塞模式
		putchar(a);
	}
}

 

順便附上老妖的減掉三倍速的1T單片機(jī)模擬串口程序。穩(wěn)定得多,當(dāng)然效率也低的多。那個(gè)是靠定時(shí)器中斷實(shí)現(xiàn)的。不過至少不會(huì)象在12T上到主程序幾乎跑不動(dòng)的地步。強(qiáng)烈要求老妖出有串口的C版本!

/*----------------------------------------------------*/
/* --- STC MCU International Limited -----------------*/
/* --- 演示STC 15 系列單片機(jī)利用定時(shí)器1實(shí)現(xiàn)模擬串口功能-----*/
/* --- Mobile: (86)13922809991 -----------------------*/
/* --- Fax: 86-755-82905966 --------------------------*/
/* --- Tel: 86-755-82948412 --------------------------*/
/* --- Web: www.STCMCU.com ---------------------------*/
/* 如果要在程序中使用或在文章中引用該程序, -----------------*/
/* 請(qǐng)?jiān)诔绦蛑谢蛭恼轮凶⒚魇褂昧薙TC的資料及程序 -------------*/
/*----------------------------------------------------*/
#include "reg51.h"
//define baudrate const
//BAUD = 256 - SYSclk/3/BAUDRATE/M (1T:M=1; 12T:M=12)
//NOTE: (SYSclk/3/BAUDRATE) must be greater than 98, (RECOMMEND GREATER THAN 110)
//開始一直看不懂為什么要除三
//#define BAUD	 0xF400 	 // 1200bps @ 11.0592MHz
//#define BAUD	 0xFA00 	// 2400bps @ 11.0592MHz
//#define BAUD	 0xFD00 	// 4800bps @ 11.0592MHz
//#define BAUD	 0xFE80 	// 9600bps @ 11.0592MHz
//#define BAUD	 0xFF40 	 //19200bps @ 11.0592MHz
//#define BAUD	 0xFFA0		 //38400bps @ 11.0592MHz
//#define BAUD	 0xEC00 	// 1200bps @ 18.432MHz
//#define BAUD	 0xF600 	 // 2400bps @ 18.432MHz
//#define BAUD	 0xFB00 	// 4800bps @ 18.432MHz
//#define BAUD	 0xFD80 	// 9600bps @ 18.432MHz
//#define BAUD	 0xFEC0 	//19200bps @ 18.432MHz
#define BAUD	 0xFF60 	 //38400bps @ 18.432MHz
//#define BAUD	 0xE800 	 // 1200bps @ 22.1184MHz
//#define BAUD	 0xF400 	 // 2400bps @ 22.1184MHz
//#define BAUD	 0xFA00 	// 4800bps @ 22.1184MHz
//#define BAUD	 0xFD00 	// 9600bps @ 22.1184MHz
//#define BAUD	 0xFE80 	//19200bps @ 22.1184MHz
//#define BAUD	 0xFF40 	 //38400bps @ 22.1184MHz
//#define BAUD	 0xFF80 	 //57600bps @ 22.1184MHz
//define UART TX/RX port
typedef bit BOOL;
typedef unsigned char BYTE;
typedef unsigned int WORD;
BYTE TBUF,RBUF;
BYTE TDAT,RDAT;
BYTE TCNT,RCNT;
BYTE TBIT,RBIT;
BOOL TING,RING;
BOOL TEND,REND;
void UART_INIT();
BYTE t, r;
BYTE buf[16];
void main()
{
    TMOD = 0x00;//timer1 in 16-bit auto reload mode
    AUXR = 0x40;//timer1 working at 1T mode
    TL1 = BAUD;//initial timer1 and set reload value
    TH1 = BAUD>>8;
    TR1 = 1;//timer1 start running[原文有錯(cuò)誤],感覺這個(gè)代碼不像老妖寫的。注釋都英文……
    ET1 = 1;//enable timer1 interrupt
    PT1 = 1;//improve timer1 interrupt priority
    EA = 1;//open global interrupt switch
    UART_INIT();
    while (1)
    {
//user's function
        if (REND)
        {
            REND = 0;
            buf[r++ & 0x0f] = RBUF;
        }
        if (TEND)
        {
            if (t != r)
            {
                TEND = 0;
                TBUF = buf[t++ & 0x0f];
                TING = 1;
            }
        }
    }
}
//-----------------------------------------
//Timer interrupt routine for UART
void tm1() interrupt 3 using 1
{
    if (RING)
    {
        if (--RCNT == 0)
        {
            RCNT = 3;//直到我看到了這里……
//reset send baudrate counter
            if (--RBIT == 0)
            {
                RBUF = RDAT; 	 //save the data to RBUF
                RING = 0;
//stop receive
                REND = 1;
//set receive completed flag
            }
            else//這TM不是坑爹吧
            {
                RDAT >>= 1;
                if (RXB) RDAT |= 0x80;
//shift RX data to RX buffer
            }
        }
    }
    else if (!RXB)
    {
        RING = 1;
//set start receive flag
        RCNT = 4;
//initial receive baudrate counter
        RBIT = 9;
//initial receive bit number (8 data bits + 1 stop bit)
    }
    if (--TCNT == 0)
    {
        TCNT = 3;
//reset send baudrate counter
        if (TING)
//judge whether sending
        {
            if (TBIT == 0)
            {
                TXB = 0;
//send start bit
                TDAT = TBUF; 	 //load data from TBUF to TDAT
                TBIT = 9;
//initial send bit number (8 data bits + 1 stop bit)
            }
            else
            {
                TDAT >>= 1;
//shift data to CY
                if (--TBIT == 0)
                {
                    TXB = 1;
                    TING = 0;
//stop send
                    TEND = 1;
//set send completed flag
                }
                else
                {
                    TXB = CY;
//write CY to TX port
                }
            }
        }
    }
}
//-----------------------------------------
//initial UART module variable
void UART_INIT()
{
    TING = 0;
    RING = 0;
    TEND = 1;
    REND = 0;
    TCNT = 0;
    RCNT = 0;
}

唉,串口之爭(zhēng)告一段落。我還是希望有硬件串口。

另外就是我實(shí)在不知道詭異的STC ISP串口是怎么在11.0592下面跑到115200的。本來加倍是溢出/16,那么它就算加倍的加倍,也就是/8……既然軟件模擬不可能實(shí)現(xiàn)如此高的波特率。而且6T模式能到230400,我就認(rèn)為他的SFR有串口四倍速選項(xiàng)。可惜老妖沒有拿出來吹,或者說他也不知道。ISP程序也讀不出。實(shí)在不知道是為啥……

順便說一句,STC15系列的片子只要RAM越界就復(fù)位……

 

順便提一個(gè)老妖的坑爹之處:

ISP定時(shí)常數(shù)不在表格中寫出來……

而是:
 

/*Define ISP/IAP/EEPROM operation const for IAP_CONTR*/
//#define 	ENABLE_IAP 	 0x80
//if SYSCLK<30MHz
//#define 	ENABLE_IAP 	 0x81
//if SYSCLK<24MHz
#define 	 ENABLE_IAP 	 0x82
//if SYSCLK<20MHz
//#define 	ENABLE_IAP 	 0x83
//if SYSCLK<12MHz
//#define 	ENABLE_IAP 	 0x84
//if SYSCLK<6MHz
//#define 	ENABLE_IAP 	 0x85
//if SYSCLK<3MHz
//#define	 ENABLE_IAP 	 0x86
//if SYSCLK<2MHz
//#define	 ENABLE_IAP 	 0x87
//if SYSCLK<1MHz


暈死……但是我為什么發(fā)現(xiàn)似乎0×83這個(gè)ISP常數(shù)到處可以用,1M的RC設(shè)置照樣0×83下……

本文轉(zhuǎn)自:http://www.rwzy.co.cc

關(guān)閉窗口

相關(guān)文章

主站蜘蛛池模板: 久久av一区二区三区 | 国产又色又爽又黄又免费 | 欧美日韩一区二区在线 | 99精品一区 | 福利视频网站 | 夜夜爽99久久国产综合精品女不卡 | 中文字幕亚洲视频 | 久久久视频在线 | 久久精品99 | 91精品国产综合久久久久久漫画 | 亚洲品质自拍视频 | 国产丝袜人妖cd露出 | 久色一区 | 国产一区在线免费观看 | 成人1区 | 黄色大片在线播放 | 亚洲一区二区三区视频 | 99亚洲视频| 中文二区| 亚洲最新网址 | 美女福利视频一区 | 久草视频网站 | 亚洲人成在线播放 | 男女在线免费观看 | 亚洲一区二区综合 | 亚洲 欧美 另类 综合 偷拍 | 国产高清美女一级a毛片久久w | 91香蕉嫩草| 久久精品国产一区 | 国产亚洲一区二区精品 | 激情久久av一区av二区av三区 | 欧美性猛交一区二区三区精品 | 欧洲成人免费视频 | 男女羞羞免费视频 | 狠狠色狠狠色综合日日92 | 欧美一区二区在线观看 | 亚洲h色 | 日韩网站在线观看 | 国产精品久久一区二区三区 | 精品国产乱码久久久久久a丨 | 91亚洲精选 |