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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 18801|回復: 1
收起左側

C51單片機串口1收發字符串方法(程序)_最后修訂無bug

[復制鏈接]
ID:26188 發表于 2015-2-18 01:28 | 顯示全部樓層 |閱讀模式
//此段包含串口1和定時器1的相關函數
/*串口編程示范說明==李斌20120802==========================================================
說明
串口接收ASCII字符,最大允許接收  Uart1_MaxString  個字符到Uart1_Data字符組,其中可包括回車
、換行符號,當接收到字0x00后,字符數組標示為可讀,在字符串接收滿后如果未接收到字0x00,所有
后續接收全部被忽略,直到接收到0x00,字符數組標示為可讀。
使用22118400晶振,最大波特率19200bit/s
串口編程示范
//文件包含
#include "STC.H"
#include <stdio.h>
#include "Uart1.c"
//函數申明
void Uart1_setup();    //初使化串口函數申明,在函數中設定串口工作方式
//主函數
void main()
{
    printf("Helloo Word");                 //使用庫函數向串口寫數據,再使用printf前必須使用過Uart1_SendString函數
    while(1)                               //主程序循環避免死機
    {
        if(Uart1.Read==1)
        {                                  //如果串口1數據可讀
            Uart1_SendString(Uart1_Data);  //串口1回送接收的數據
            Uart1.Read=0;                  //串口1不可讀(已讀,為下次讀出做準備)
        }
    }
}
//初使化串口函數 ,必須寫在主函數尾,在主函數頭部申明并引用
void Uart1_setup()
{
for(Uart1.Data_P=0;Uart1.Data_P<=Uart1_MaxString;Uart1.Data_P++)
{//清空串口1接收字串內容,寫0x00
    Uart1_Data[Uart1.Data_P]='\0';
}
Uart1.Data_P= 0;                //串口1接收字串下標歸0
Uart1.ParitySet= 0;             //串口1使用9位可變波特率方式,校驗方式為無校驗, 0無校驗,1:奇校驗,2:偶校驗,3:校驗=1,4:校驗=0
Uart1_Setup(19200,0);           //串口1波特率為19200bps,時基源選擇定時器1 ,  0為定時器1,1為獨立波特率發生器
}
=======================================================================================*/
//包含文件定義

//串口相關常量定義
#define  FOSC              22118400L   //系統頻率11059200L 22118400L
#define  Uart1_MaxString   64          //串口1最大接收緩沖區字符數量
//串口相關變量定義
char  xdata          Uart1_Data[Uart1_MaxString+1]; //串口1接收字串
struct Uart1
{//串口1結構數據類型
    unsigned char        Data_P;                //串口1接收字串位置指針
    unsigned char        ParitySet;             //串口1奇偶校驗方式 0不校驗 1奇校驗 2偶校驗 3始終1 4始終0
    unsigned char        Busy:1;                //串口1正在發送標記,1,正在發送,0,發送完成 ,保留未使用
    unsigned char        Read:1;                //串口1接受字符組可讀標記
    unsigned char        Parity:1;              //串口1接收到的奇偶校驗狀態 1,0
    unsigned char        Parity_out:1;          //串口1驗證接收到的奇偶校驗狀態 1,驗證,0驗證錯誤
}Uart1;                                         //結構變量名
//Uart1包含函數申明
void Uart1_Setup(unsigned long Uart1_Baud,bit Uart1_Tx); //串口1波特率和時基源設置函數
void Uart1_chars_Int();                                  //串口1中斷服務函數采用字符數組接收以'\0'為停止符的實際內容
void Uart1_SendData(unsigned char Uart1_dat);            //串口1單字符發送函數
void Uart1_SendString(char *s);                          //串口1字符串發送函數
//非必要包含的函數申明
//void Time1_Isr() interrupt 3 using 1;                  //定時器1中斷服務函數入口
//void Uart1_Isr() interrupt 4 using 1;                  //串口1中斷服務函數入口
/*********************************************************
** 函數名稱: void Uart1_Setup(unsigned long Uart1_Baud,bit Uart1_Tx)
** 功能描述: 初始化串口函數
** 輸   入: unsigned long Uart1_Baud,bit Uart1_Tx
** 輸   出: 無
** 全局變量: PCON,SCON,TMOD,AUXR,TCON,TH1,
** 調用模塊:
** 備    注:時鐘為22118400Hz
            參數1:波特率設置,300;600;1200;2400;4800;9600;19200
            參數2:計數器選擇,0,定時器1;1,獨立波特率
**********************************************************/
void Uart1_Setup(unsigned long Uart1_Baud,bit Uart1_Tx)
{
unsigned int Uart1_Brt;       //串口定時器重裝值臨時存儲位
//時基源設置-------------------------------------------------
if(Uart1_Tx)
{
    AUXR |= 0x01;  //串口1選擇獨立波特率發生器
}
else
{
    AUXR &= 0xFE;  //串口1選擇定時器1做波特率發生器
}
//校驗方式設置-------------------------------------------------
switch(Uart1.ParitySet)
{//判斷校驗方式
    case 1:SCON=0xD8;break;   //9位串口, 奇校驗
    case 2:SCON=0xD4;break;   //9位串口, 偶校驗
    case 3:SCON|=0xD8;break;  //9位串口, 掩碼校驗,校驗值始終為 1
    case 4:SCON=0xD4;break;   //9位串口, 空校驗
    default:
    {//8位串口, 無校驗 Uart1.ParitySet=0; 校驗位初值狀態標記置0
        SCON&=0x5F;         //清除第5位,第7位
        SCON|=0x50;         //8位波特率可變,允許接收
        break;
    }
}
//波特率設置并開始運行串口-------------------------------------------------
//時鐘為22118400Hz
Uart1_Brt=FOSC/32/Uart1_Baud;
if(Uart1_Brt>255)
{//如果重裝值>255,使用12T模式12分頻
    if(Uart1_Tx)
    {//如果使用獨立波特率發生器
        AUXR &= 0xFB;                               //獨立波特率使用12T模式
        BRT = 256-Uart1_Brt/12;                     //獨立波特率發生器初值設置
        AUXR|= 0x10;                                //獨立波特率發生器開始計數
    }
    else
    {//如果使用定時器1做波特率發生器
        TMOD&=0xCF;                                 //清除定時器1設置狀態,定時器0不修改
        TMOD|=0x20;                                 //定時器1使用8位自動重裝模式
        AUXR &= 0xBF;                               //定時器1使用12T模式
        TH1  = TL1 = 256-Uart1_Brt/12;              //設置自動裝入的值
        //ET1  = 1;                                 //允許定時器1中斷=========使用定時器1中斷做串口中斷時書寫
        TR1  = 1;                                   //TCON|=0x40;定時器1開始計數,TCON&=0xBF;關閉計數
    }
}
else
{//如果重裝值<255,使用1T模式1分頻
    if(Uart1_Tx)
    {//如果使用獨立波特率發生器
        AUXR |= 0x04;                               //獨立波特率使用1T模式
        BRT  = 256-Uart1_Brt;                       //獨立波特率發生器初值設置
        AUXR|= 0x10;                                //獨立波特率發生器開始計數
    }
    else
    {//如果使用定時器1做波特率發生器
        TMOD&=0xCF;                                 //清除定時器1設置狀態,定時器0不修改
        TMOD|=0x20;                                 //定時器1使用8位自動重裝模式
        AUXR|=0x40;                                 //定時器1使用1T模式
        TH1  = TL1 = 256-Uart1_Brt;                 //設置自動裝入的值
        //ET1  = 1;                                 //允許定時器1中斷=========使用定時器1中斷做串口中斷時書寫
        TR1  = 1;                                   //TCON|=0x40;定時器1開始計數,TCON&=0xBF;關閉計數
    }
}
    TI   = 1;                                       //兼容系統函數printf,需要先對TI置1
    ES        = 1;                                  //打開串口中斷
    EA        = 1;                                  //打開總中斷
}

//=======================================================================================
/**********************************************************
串口1中斷服務函數
**********************************************************/
void Uart1_Isr() interrupt 4 using 1
{
Uart1_chars_Int();
}
void Uart1_chars_Int()
{
//EA=0;
    if (RI)
    {//如果 UART 接收產生中斷
        RI = 0;                                           //清除 UART 接收中斷標記
        //TF1=0;                                          //清除定時器1的中斷標記,在使用串口中斷時,這行不寫
        ACC= SBUF;                                        //接收緩沖區數據寫入累加器A
        Uart1.Parity = P;                                 //保存校驗值到Uart1_Parity
        Uart1.Parity_out=0;                               //清除允許寫入標記,為下面判斷準備
        switch(Uart1.ParitySet)
        {//根據校驗要求判斷
            case 0:Uart1.Parity_out=1; break;                   //要求無校驗,如果無校驗,允許寫入
            case 1:Uart1.Parity_out=Uart1.Parity^RB8; break;    //要求奇校驗,如果檢驗結果和接收結果不符合則成立,允許寫入
            case 2:Uart1.Parity_out=~(Uart1.Parity^RB8);break;  //要求偶校驗,如果檢驗結果和接收結果符合則成立,允許寫入
            case 3:Uart1.Parity_out=RB8; break;                 //要求常1校驗,如果接收結果為1則成立,允許寫入
            case 4:Uart1.Parity_out=~RB8; break;                //要求常0校驗,如果接收結果為0則成立,允許寫入
            default:Uart1.Parity_out=0;break;                   //非法的參數,不接收
        }
        if(Uart1.Parity_out)
        {//如果允許寫入
            if(Uart1.Data_P<Uart1_MaxString)
            {//如果接受字符組指針小于字符數組最大下標減1(字符數組最后一位始終為0x00,方便指針做底判斷)
                if(SBUF=='\0')
                {//如果接受字符是0x00
                    Uart1_Data[Uart1.Data_P]=SBUF;    //接受數據寫入字符數組
                    Uart1.Data_P=0;                   //字符數組下標歸0
                    Uart1.Read=1;                     //串口數據可讀
                }
                else
                {//如果接受字符不是0x00
                    Uart1_Data[Uart1.Data_P]=SBUF;    //接受數據寫入字符數組
                    Uart1.Data_P++;                   //字符數組下標自加1
                }
            }
            else
            {//如果接受字符組指針大于等于字符數組最大下標減1
                if(SBUF=='\0')
                {//如果接受字符是0x00
                    Uart1.Data_P=0;                   //字符數組下標歸0
                    Uart1.Read=1;                     //串口數據可讀
                }
            }
        }
    }
/*
    if (TI)
    {//如果 UART 發送產生中斷
    }
*/
    /*=============使用定時器1中斷時需要書寫,使用串口中斷時忽略
    if(TF1)
    {
        TF1=0;   //清定時器1中斷標記
    }
    =============*/
//EA=1;
}

//=======================================================================================
/**********************************************************
** 函數名稱: void Uart1_SendData(unsigned char Uart1_dat)
** 功能描述: UART1 單個字符發送函數
** 輸   入: unsigned char Uart1_dat
** 輸   出: 無
** 全局變量:
** 調用模塊:
** 備    注:參數1:待發送的單個字符
**********************************************************/
void Uart1_SendData(unsigned char Uart1_dat)
{//UART 發送字節函數
bit TB8_Temp;
    ACC = Uart1_dat;                   //被發送數據送累加器A,準備求奇偶校驗位 P
    TB8_Temp = P;                      //寫奇偶校驗標記
    while (~TI);                //循環等待正在發送標記被清空
TI=0;
    switch(Uart1.ParitySet)
    {//根據校驗要求判斷
        case 0:TB8=0;break;            //要求無校驗
        case 1:TB8=~TB8_Temp;break;    //要求奇校驗,翻轉TB8的值
        case 2:TB8=TB8_Temp;break;     //偶校驗,TB8不變
        case 3:TB8=1;break;            //要求常1校驗,TB8恒等于1
        case 4:TB8=0;break;            //要求常0校驗,TB8恒等于0
        default: break;                //要求無校驗
    }
    SBUF = Uart1_dat;                  //累加器 A 中的數據送發送緩沖區發送

}
//=======================================================================================
/**********************************************************
** 函數名稱: void Uart1_SendString(char *s)
** 功能描述: UART1 按字符串發送函數
** 輸   入: char *s
** 輸   出: 無
** 全局變量:
** 調用模塊:
** 備    注:參數1:待發送的字符串
**********************************************************/
void Uart1_SendString(char *s)
{//UART 按字符串發送
    while (*s)
    {
        Uart1_SendData(*s++);   //將待發字符串依次使用SendData函數按字節發送
    }
}
//=======================================================================================
/*常用串口設置開關===============================附錄====================================
AUXR |= 0x01;  //串口1選擇獨立波特率發生器
AUXR &= 0xFE;  //串口1選擇定時器1做波特率發生器
AUXR |= 0x40;  //定時器1使用1T模式
AUXR &= 0xBF;  //定時器1使用12T模式
AUXR |= 0x04;  //獨立波特率使用1T模式
AUXR &= 0xFB;  //獨立波特率使用12T模式
AUXR |= 0x10;  //打開獨立波特率發生器
AUXR &= 0xEF;  //關閉獨立波特率發生器
PCON |= 0x80;  //串口1波特率加倍
PCON &= 0x7f;  //串口1波特率不加倍
AUXR |= 0x08;   //串口2波特率加倍
AUXR &= 0xf7;   //串口2波特率不加倍
==========================================================================================*/




回復

使用道具 舉報

ID:98880 發表于 2018-5-22 23:14 | 顯示全部樓層
這個可以做成模塊化的嗎?
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 91视频一区二区 | 亚洲精品久久久 | 精品国产一区二区 | 午夜婷婷激情 | 一区二区在线不卡 | 天天拍夜夜爽 | 久久999| 亚欧洲精品在线视频免费观看 | 欧美乱做爰xxxⅹ久久久 | 久久机热 | 91亚洲国产成人精品一区二三 | 欧美jizzhd精品欧美巨大免费 | 久久久久久久久久久91 | 99日韩| 欧美成人精品一区二区男人看 | 天天草草草 | 亚洲 欧美 精品 | 欧美一区二区三区四区在线 | 国产精品美女在线观看 | cao视频 | 国产成人在线视频 | 一区二区三区国产好 | 久久久男人的天堂 | 国产精品毛片一区二区在线看 | 涩涩导航| 日本成人二区 | 欧美精品一区在线发布 | 日韩国产高清在线观看 | 免费超碰 | 午夜视频导航 | 九九亚洲 | 久久这里有精品 | 看片91| 亚洲激情综合 | 精品91久久| 中文字幕av中文字幕 | av免费观看网站 | 亚洲网在线| 欧美综合视频在线 | 亚洲欧美日韩精品久久亚洲区 | 99久久久久 |