正文

把LPC900的串口模拟程序移植到了LPC922,很稳定2008-04-12 20:18:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/niao0311/34105.html

分享到:

把LPC900的串口模拟程序移植到了LPC922,很稳定
 
 
yuzhuju 发表于 2005-6-14 11:49 Philips LPC900单片机

感觉LPC900写的程序可读性很好,不像有些网友的C语言里面都偏僻语法,看上去好象很高深厉害,实际可读性一点都不好.第一次用模拟串口,感觉收发很稳定,谢谢LPC900.

/*用I/O模拟串行口例程(LPC900)
    下面的程序是我以前写的,适合于80C52内核的单片机,不能直接用在LPC900系列单片机上。我现在懒了,
    不想再修改,如果要用,您自己动手做一些修改吧:
    首先,该程序中的定时器用的是T2,然而LPC900系列单片机中没有T2。您可以将其换成T0或者是T1。
    RXD_pin和TXD_pin的属性要重新做一些设置,使之能够在您的LPC900单片机上运行。
    晶振不能用22.1184MHz那么高,建议用低于12MHz的晶振或者直接使用片内RC振荡器。
*/

/*
    52单片机实用的IO模拟串行口C语言源程序
    作者:LPC900
    移植: saint(yuzhuju)
    用途:短距离、波特率要求不高、环境干扰不大的场合
    特点:
        程序简练、实用、移植方便
        占用定时器T0
        只消耗约600字节的ROM
        有详细的注释
    参数:
        晶振  :7.373MHz
        波特率:2400
        起始位:1
        数据位:8
        校验位:无
        停止位:1
    -----------------------
    yuzhuju:
    感觉程序中的HITS只有在判断开始位时,才有实际意义,
    其它HITS使用场合中,如果不是每次采样都和上次结果作比较判断,意义就不是很大,只能凑个接收周期
    不知道理解对不对.
    -----------------------
*/

extern void Uart2Init(void);//初始化
extern void TXD_Send_String(const unsigned char s[]);//发送字符串函数
extern void Uart2Task(void);//放在主函数WHILE(1)中,一旦收到结束符号'?',把RXD_buf中收到的数据发送回来

 

#i nclude <REG922.H>

//修改如下定义将方便程序移植
sbit RXD_pin = P0^4;  //定义接收引脚
sbit TXD_pin = P0^5;  //定义发送引脚
#define MAIN_CLK    7373000    //定义主频
#define BAUD_RATE   2400       //定义波特率(数值不能太高,因为要给T2中断服务程序留足执行时间)
#define HITS        8          //定义采样率(应当是偶数;减少采样率能提高波特率,但为保证可靠工作,最小不能少于6次)

#define RXD_BUF_LEN  16  //定义接收缓冲区大小
volatile unsigned char RXD_buf[RXD_BUF_LEN];  //定义接收缓冲区(循环队列)
volatile unsigned char RXD_p1;  //指向缓冲区,由中断程序自动修改
volatile unsigned char RXD_p2;  //指向缓冲区,由主程序修改

#define TXD_BUF_LEN  16  //定义发送缓冲区大小
volatile unsigned char TXD_buf[TXD_BUF_LEN];  //定义发送缓冲区(循环队列)
volatile unsigned char TXD_p1;  //指向TXD_buf,由主程序修改
volatile unsigned char TXD_p2;  //指向TXD_buf,由中断程序修改
volatile bit U2TEnable;

//定时器T0初始化
void Time0Init(void)
{
    unsigned char TimeValue;
    TAMOD&=(~0x01);//T0M2=0
    TMOD|=0X02;//T0M1=1
    TMOD&=(~0X01);//T0M0=0,T0 MODE 2
    TMOD&=(~0X04);//设置为定时器功能;
    TMOD&=(~0X08);//设置为TR0使能定时器
    IP0H|=0x02;//设置T0为最高优先级中断
    IP0|=0x02;
       TimeValue=256 - ( MAIN_CLK / 2 ) / ( BAUD_RATE * HITS );  //此公式值得你琢磨一下
    //好象只能设置到2400,再低就要溢出了
    TH0 = TimeValue;
    TL0 = TimeValue;
       ET0= 1;
    TR0 = 1;
}


//接收初始化
void RXDInit(void)
{
    unsigned char i;
    P0M1 &= ~(0X01 << 4); //PortSet(0,4,GPIO);把P0.4设置为GPIO
    P0M2 &= ~(0X01 << 4);
    RXD_pin = 1;
    RXD_p1 = 0;
    RXD_p2 = 0;
    for(i=0;i<16;i++)//RXD_BUF_LEN
    {
        RXD_buf[i] = 0x00;
    }
}


//发送初始化
void TXDInit(void)
{
    unsigned char i;
    P0M1 &= ~(0X01 << 5); //PortSet(0,5,GPIO);把P0.5设置为GPIO
    P0M2 &= ~(0X01 << 5);
    TXD_pin = 1;
    TXD_p1 = 0;
    TXD_p2 = 0;
    for ( i=0; i< TXD_BUF_LEN; i++ )
    {TXD_buf[i] = 0x00;}
}

//发送单个字符
void TXD_Send_Char(const unsigned char c)
{
    unsigned char p;  //临时变量
    p = TXD_p1 + 1;
    if ( p >= TXD_BUF_LEN ) p = 0;
    while ( p == TXD_p2 );  //判断发送缓冲队列是否已满,如果是,则暂时不能发送
    TXD_buf[TXD_p1] = c;  //先将c写入队列
    TXD_p1 = p;  //再修改TXD_p1
    //在T2中断服务程序里会自动完成发送
}

//发送字符串(不包括末尾的'\0')
void TXD_Send_String(const unsigned char s[])
{
    unsigned char c;
    unsigned int i = 0;
        for (;;)
        {
            c = s[i++];
            if ( c == '\0' ) break;
            TXD_Send_Char(c);
        }
}


//定义接收缓冲字符
volatile unsigned char bdata RXD_ch;
sbit RXD_ch_MSB = RXD_ch^7;

//定义发送缓冲字符
volatile unsigned char bdata TXD_ch;
sbit TXD_ch_LSB = TXD_ch^0;

//T2中断服务程序
//每中断HITS次处理1位
static void IRQTIME0() interrupt 1 using 3
{
//定义接收所需要的变量
    static bit RXD_doing = 0;  //正在接收的标志
    static unsigned char RXD_t = HITS/2;  //接收时计数T2的中断次数
    static unsigned char RXD_cnt;  //接收时bit位的计数器
//定义发送所需要的变量
    static bit TXD_doing = 0;  //正在发送的标志
    static unsigned char TXD_t;  //发送时计数T2的中断次数
    static unsigned char TXD_cnt;  //发送时bit位的计数器
//先清除TF2
    TF0 = 0;
//接收数据
    if( RXD_doing )  //正处于接收状态
        {
        if( --RXD_t == 0 )  //经过了HITS个采样脉冲
           {
            if( RXD_cnt == 0 )  //8个数据位接收完毕
                {
                if( RXD_pin )  //检测到停止位
                        {
                                RXD_t = RXD_p1 + 1;  //在这里,RXD_t作为临时变量
                                if ( RXD_t >= RXD_BUF_LEN ) RXD_t = 0;
                                if ( RXD_t != RXD_p2 )  //如果接收缓冲队列未满
                                {
                                    RXD_buf[RXD_p1] = RXD_ch;
                                    RXD_p1 = RXD_t;
                                    if(RXD_ch=='?'){U2TEnable=1;}
                                }
                                else
                                {
                                    //如果接收缓冲队列已满,只好丢弃新收到数据
                                }
                        }
                        else  //检测停止位时出错
                        {
                                //舍弃新收到的数据
                        }
                        RXD_doing = 0;  //接收全部完毕,清除正在接收的标志
                        RXD_t = HITS/2;  //恢复RXD_t的初始值
                    }
                    else  //接收数据位
                    {
                        RXD_ch >>= 1;
                        RXD_ch_MSB = RXD_pin;
                        //上面2条语句若用{CY=RXD_pin; CY=(RXD_ch&0x01); RXD_ch=ACC;}代替,效率更高
                        RXD_cnt--;
                        RXD_t = HITS;
                    }
            }
    }
    else  //检测起始位[/#]
    {
            if ( RXD_pin )
            {
                    RXD_t = HITS/2;
            }
            else
            {
                    RXD_t--;
                    if ( RXD_t == 0 )  //连续HITS/2次采样RXD_pin都是0,就可以确认起始位
                    {
                       //启动接收
                      RXD_t = HITS;
                      RXD_cnt = 8;
                      RXD_doing = 1;
            }
            }
    }
//发送数据
    if ( TXD_doing )  //正处于发送状态
        {
            TXD_t--;
            if ( TXD_t == 0 )
            {
                    if ( TXD_cnt == 0 )  //发送全部完毕
                    {
                        TXD_doing = 0;  //清除正在发送的标志
                    }
                    else
                    {
                        if ( TXD_cnt == 1 )  //8个数据位发送完毕
                        {
                                TXD_pin = 1;  //发送停止位
                        }
                        else  //发送数据位
                        {
                                TXD_pin = TXD_ch_LSB;
                                TXD_ch >>= 1;
                            //上面2条语句若用{CY=(TXD_ch&0x01); TXD_pin=CY; TXD_ch=ACC;}代替,效率更高
                        }
                        TXD_cnt--;
                        TXD_t = HITS;
                    }
            }
        }
        else
        {
            if ( TXD_p2 != TXD_p1 )  //如果发送缓冲队列不空
            {
                //从发送缓冲队列中取出要发送的数据
                    TXD_ch = TXD_buf[TXD_p2++];
                    if ( TXD_p2 >= TXD_BUF_LEN ) TXD_p2 = 0;
                //启动发送
                    TXD_doing = 1;
                    TXD_cnt = 9;
                    TXD_t = HITS;
                //先发送起始位
                    TXD_pin = 0;
            }
            else
            {
                    //发送缓冲队列是空的,不发送任何数据
            }
        }
}


//系统初始化
void Uart2Init(void)
{
    TXDInit();
    RXDInit();
    Time0Init();
    U2TEnable=0;
}


void Uart2Task(void)
{   
    unsigned char c;
    if(U2TEnable)
    {
        while ( RXD_p2 != RXD_p1 )
        {
            c = RXD_buf[RXD_p2++];
            if ( RXD_p2 >= RXD_BUF_LEN ) RXD_p2 = 0;
            TXD_Send_Char(c);
        }
           TXD_Send_String("Return Data Over.\r\n");
        U2TEnable=0;
    }
}
//主程序
void main(void)
{
    Uart2Init();
    TXD_Send_String("The author is 21IC LPC900.\r\n");
    {
        Uart2Task();
    }

}

阅读(2035) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册