世俱杯 2025

登录 免费注册 世俱杯 2025 | 行业黑名单 | 帮助
维库电子市场网
技术交流 | 电路欣赏 | 工控天地 | 数字广电 | 通信技术 | 电源技术 | 测控之家 | EMC技术 | ARM技术 | EDA技术 | PCB技术 | 嵌入式系统
驱动编程 | 集成电路 | 器件替换 | 模拟技术 | 新手园地 | 单 片 机 | DSP技术 | MCU技术 | IC 设计 | IC 产业 | CAN-bus/DeviceNe

LPC900,请教一个模拟串口问题

作者:zy005021 栏目:MCU技术
LPC900,请教一个模拟串口问题
LPC900,请教一个模拟串口问题,我看了前面提供的那个模拟串口的程序,但是我的电路还没有搭出来的情况下,我想先在KEIL C下模拟一下这个模拟串口,让它通过一根九针线缆发送给另外一台计算机.我以前是用单片机的串口模拟的,可以实现,但是模拟串口就不知道能不能实现了.
希望能指点一下:)

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


/*
    52单片机实用的IO模拟串行口C语言源程序
    作者:LPC900
    用途:短距离、波特率要求不高、环境干扰不大的场合
    特点:
        程序简练、实用、移植方便
        占用定时器T2
        只消耗约600字节的ROM
        有详细的注释
    参数:
        晶振:22.1184MHZ
        波特率:1200
        起始位:1
        数据位:8
        校验位:无
        停止位:1
*/



#include <reg52.h>


//将T2定时器的自动重装寄存器定义成16位SFR,以方便访问
sfr16 RCAP2 = 0xCA;


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

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

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


//定时器T2初始化
extern void T2_init()
{
    EA = 0;
    T2CON = 0x00;
    PT2 = 1;  //将T2中断设置成高级优先级
    RCAP2 = 65536L - ( MAIN_CLK / 12 ) / ( BAUD_RATE * HITS );  //此公式值得你琢磨一下
    TH2 = RCAP2H;
    TL2 = RCAP2L;
    ET2 = 1;
    TR2 = 1;
    EA = 1;
}


//接收初始化
extern void RXD_init()
{
    unsigned CHAR i;
    RXD_pin = 1;
    RXD_p1 = 0;
    RXD_p2 = 0;
    for ( i=0; i<RXD_BUF_LEN; i++ )
    {
        RXD_buf[i] = 0x00;
    }
}


//发送初始化
extern void TXD_init()
{
    unsigned CHAR i;
    TXD_pin = 1;
    TXD_p1 = 0;
    TXD_p2 = 0;
    for ( i=0; i< TXD_BUF_LEN; i++ )
    {
        TXD_buf[i] = 0x00;
    }
}

//发送单个字符
extern 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')
extern 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 T2INTSVC() interrupt 5 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; &
3楼: >>参与讨论
zy005021
谢谢,再请问一下
谢谢给予的回答,我现在在做一个通讯转发的程序,要实现的功能是,单片机从一个采集模块接收数据,再转发给一台计算机和一个GPRS系统,请问是不是可以先通过单片机的固有串口接受数据,再通过设置的两个模拟串口转发数据来实现?还有没有其他的办法来实现呢??
请教一下:)

4楼: >>参与讨论
LPC900
用I/O模拟串行口是最便宜的方案
    转发数据的方法很多。用I/O模拟串行口是最便宜的方案,只是速度不够快。还有快速的方案:采用双口RAM,但是价钱就高了。还有一种方法是采用专门的串行口扩展芯片,比软件模拟要快。

5楼: >>参与讨论
zy005021
你的这个模拟串口的速率能不能达到4800?
你的这个模拟串口的速率能不能达到4800?

6楼: >>参与讨论
LPC900
没问题,可以达到4800
如果使用LPC900系列单片机,软件模拟串行口的波特率完全可以达到4800,因为LPC900比标准80C51快6倍。

7楼: >>参与讨论
zy005021
LPC900,再提一个问题
51 IO口模拟串口通讯C源程
#include <reg51.h>
sbit BT_SND =P1^0;
sbit BT_REC =P1^1;
/**********************************************

IO 口模拟232通讯程序

使用两种方式的C程序 占用定时器0

**********************************************/

#define MODE_QUICK

#define F_TM F0

#define TIMER0_ENABLE TL0=TH0; TR0=1;
#define TIMER0_DISABLE TR0=0;

sbit ACC0= ACC^0;
sbit ACC1= ACC^1;
sbit ACC2= ACC^2;
sbit ACC3= ACC^3;
sbit ACC4= ACC^4;
sbit ACC5= ACC^5;
sbit ACC6= ACC^6;
sbit ACC7= ACC^7;

void IntTimer0() interrupt 1
{
F_TM=1;
}
//发送一个字符
void PSendChar(unsigned CHAR inch)
{
#ifdef MODE_QUICK
ACC=inch;

F_TM=0;
BT_SND=0; //start bit
TIMER0_ENABLE; //启动
while(!F_TM);

BT_SND=ACC0; //先送出低位
F_TM=0;
while(!F_TM);

BT_SND=ACC1;
F_TM=0;
while(!F_TM);

BT_SND=ACC2;
F_TM=0;
while(!F_TM);

BT_SND=ACC3;
F_TM=0;
while(!F_TM);

BT_SND=ACC4;
F_TM=0;
while(!F_TM);

BT_SND=ACC5;
F_TM=0;
while(!F_TM);

BT_SND=ACC6;
F_TM=0;
while(!F_TM);

BT_SND=ACC7;
F_TM=0;
while(!F_TM);

BT_SND=1;
F_TM=0;
while(!F_TM);


TIMER0_DISABLE; //停止timer
#else
unsigned CHAR ii;

ii=0;

F_TM=0;
BT_SND=0; //start bit
TIMER0_ENABLE; //启动
while(!F_TM);

while(ii<8)
{
if(inch&1)
{
BT_SND=1;
}
else
{
BT_SND=0;
}
F_TM=0;
while(!F_TM);
ii++;
inch>>=1;
}
BT_SND=1;
F_TM=0;
while(!F_TM);

#endif
TIMER0_DISABLE; //停止timer
}
//接收一个字符
unsigned CHAR PGetChar()
{
#ifdef MODE_QUICK

TIMER0_ENABLE;
F_TM=0;
while(!F_TM); //等过起始位
ACC0=BT_REC;

TL0=TH0;

F_TM=0;
while(!F_TM);
ACC1=BT_REC;

F_TM=0;
while(!F_TM);
ACC2=BT_REC;

F_TM=0;
while(!F_TM);
ACC3=BT_REC;

F_TM=0;
while(!F_TM);
ACC4=BT_REC;

F_TM=0;
while(!F_TM);
ACC5=BT_REC;

F_TM=0;
while(!F_TM);
ACC6=BT_REC;

F_TM=0;
while(!F_TM);
ACC7=BT_REC;

F_TM=0;

while(!F_TM)
{
if(BT_REC)
{
break;
}
}
TIMER0_DISABLE; //停止timer
return ACC;
#else
unsigned CHAR rch,ii;
TIMER0_ENABLE;
F_TM=0;
ii=0;
rch=0;
while(!F_TM); //等过起始位

while(ii<8)
{
rch>>=1;
if(BT_REC)
{
rch|=0x80;
}
ii++;
F_TM=0;
while(!F_TM);

}
F_TM=0;
while(!F_TM)
{
if(BT_REC)
{
break;
}

}
TIMER0_DISABLE; //停止timer
return rch;

#endif

}
//检查是不是有起始位
bit StartBitOn()
{
return (BT_REC==0);

}
void main()
{
unsigned CHAR gch;

TMOD=0x22; /*定时器1为工作模式2(8位自动重装),0为模式2(8位
自动重装) */
PCON=00;

TR0=0; //在发送或接收才开始使用
TF0=0;
TH0=(256-96); //9600bps 就是 1000000/9600=104.167微秒 执行的
timer是
//
104.167*11.0592/12= 96
TL0=TH0;
ET0=1;
EA=1;

PSendChar(0x55);
PSendChar(0xaa);
PSendChar(0x00);
PSendChar(0xff);

while(1)
{
if(StartBitOn())
{
gch=PGetChar();
PSendChar(gch);
}
}
}
这同样是一个51模拟串口的程序,为什么写得这么简单呢?这样写的话,通讯还正常吗????因为我没有在硬件上调试,因此不知道这个和你那个程序的结果谁更稳定.



8楼: >>参与讨论
LPC900
解决同一个问题,不同的人写出程序往往是不同的
    我写的程序特点是:程序书写格式好、实用、移植方便。上面那个程序不知是不是你写的,但第一眼看上去,程序书写格式极差,连Tab缩进都没有,由于这容易造成理解上的困难,我已经不想看下去。第二眼看过去,C51源程序中竟然去操控累加器ACC,良好的C51编程风格只会访问SFR寄存器而不会去引用系统寄存器的,我看不下去了。第三眼,已经没有第三眼了。
    最后你说“没有在硬件上调试”,那先调试了再说。我的程序是经过多次软硬件调试通过的。

参与讨论
昵称:
讨论内容:
 
 
相关帖子
zlg7290的单击和连击问题?
请问LPC900在使用内部WDT时钟时电流消耗.
请问,lpc932系列flash单片机应用技术   一书中的程序例程
请问zlg900
关于iap,


Copyright © 1998-2006 tgdrjb.cn 浙ICP证030469号