cpubbs论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

LabVIEW+单片机学习套件全套教程资料下载[免费]LabVIEW论坛精华列表贴USB0816数据采集卡《LabVIEW宝典》
LabWindows/CVI论坛精华贴NET0816以太网数据采集卡RC0210远程设备授权系统 关闭关停锁定打开设备 户外分布式数据采集
NET1624低速高精度以太网数据采集卡WIFI0824SD无线WIFI网络数据采集卡脱机运行 SD存储 小尺寸微型 串口采集远程采集 安卓 手持移动采集 纪录仪
查看: 2004|回复: 0

16C550在51系统中的应用--C51例程

[复制链接]
发表于 2004-11-6 03:04:20 | 显示全部楼层 |阅读模式
<>16C550在51系统中的应用--C51例程

    作者:adlion
</P>
<>下面这段程序是我在一个项目中驱动16C552使用的,其实16C552是两个16C550和一个并
口合在一个芯片里,在实际的操作上和16c550并没有什么不同,可以看成是对两个独立的
16C550操作。
    在下面的程序中,采用的是中断方式,同时使用了FIFO,具体的设置可以看看程序中相
关部分。
    为节省篇幅,在中断处理程序中,我省略了一个串口的处理,其实两个串口的处理是相
同的。
    或许有朋友在使用16C554,16C554其实也就是4个16C550的集合,不过由于单片机的中断
有限,这4个串口往往共用一个中断,在这是就要注意中断的处理了,以后有时间我写个
16C554的处理程序上来^_^
    以下程序本人不保证正确性和稳定性(虽然在我的系统中很正常,不过这句话按照惯例
还是说一次^_^)
    下面是我编写的一个小程序(用JavaScript和表单编写),用于计算DLL的装载值。输
入频率和预期的波特率,点击“计算”就可以了。

晶振频率(MHz): (mhz)
波特率(bps): (bps)  

装载值(DLL)【十进制,计算值出现小数表示在此晶振频率下使用该波特率有误差】  



//------------------------------------------------------------------------------
---------------------
// 项目:
//   文件: u550.c
// 描述: 16c552的控制程序
// 编译: adlion
// 版本: 1.0
// 创建日期: 2001-12-10
// 最后修订:   2002-04-01
// 编译环境:  Keil C51 V6.23
//------------------------------------------------------------------------------
---------------------


#include "ftu.h"


#define adr_552_base  0xc000
//这里定义地址,具体的地址定义要看系统连接了
//串口1
#define uc_552a_thr  XBYTE[adr_552_base+0x000] // Transmit Holding
Register
#define uc_552a_rhr  XBYTE[adr_552_base+0x000] // Receive Holding
Register
#define uc_552a_ier  XBYTE[adr_552_base+0x100] // Interrupt Enable
Register
#define uc_552a_isr  XBYTE[adr_552_base+0x200] // Interrupt Status
Register
#define uc_552a_fcr  XBYTE[adr_552_base+0x200] // FIFO control register
#define uc_552a_lcr  XBYTE[adr_552_base+0x300] // Line control Register
#define uc_552a_mcr  XBYTE[adr_552_base+0x400] // Modem Control Register
#define uc_552a_lsr  XBYTE[adr_552_base+0x500] // Line Status Register
#define uc_552a_msr  XBYTE[adr_552_base+0x600] // Modem Status Register
#define uc_552a_spr  XBYTE[adr_552_base+0x700] // Scratchpad Register

#define uc_552a_dll  XBYTE[adr_552_base+0x000]
#define uc_552a_dlm  XBYTE[adr_552_base+0x100]


//串口2
#define uc_552b_thr  XBYTE[adr_552_base+0x800] // Transmit Holding
Register
#define uc_552b_rhr  XBYTE[adr_552_base+0x800] // Receive Holding
Register
#define uc_552b_ier  XBYTE[adr_552_base+0x900] // Interrupt Enable
Register
#define uc_552b_isr  XBYTE[adr_552_base+0xa00] // Interrupt Status
Register
#define uc_552b_fcr  XBYTE[adr_552_base+0xa00] // FIFO control register
#define uc_552b_lcr  XBYTE[adr_552_base+0xb00] // Line control Register
#define uc_552b_mcr  XBYTE[adr_552_base+0xc00]   // Modem Control Register
#define uc_552b_lsr  XBYTE[adr_552_base+0xd00] // Line Status Register
#define uc_552b_msr  XBYTE[adr_552_base+0xe00] // Modem Status Register
#define uc_552b_spr  XBYTE[adr_552_base+0xf00] // Scratchpad Register

#define uc_552b_dll  XBYTE[adr_552_base+0x800]
#define uc_552b_dlm  XBYTE[adr_552_base+0x900]

//并口
#define uc_552_pr XBYTE[adr_552_base+0x1000] // Port Register
#define uc_552_iosel XBYTE[adr_552_base+0x1100] // I/O Select Register
#define uc_552_sr XBYTE[adr_552_base+0x1100] // Status Register
#define uc_552_com XBYTE[adr_552_base+0x1200] // Command Register
#define uc_552_con XBYTE[adr_552_base+0x1200] // Control Register

//缓冲区
#define uc_552a_buf_len  64
xdata unsigned char uc_552atxd_buf[uc_552a_buf_len];
xdata unsigned char uc_552arxd_buf[uc_552a_buf_len];
idata unsigned char uc_552atxd_out,uc_552atxd_in;
idata unsigned char uc_552arxd_out,uc_552arxd_in;
bit b_552atxd_done;
bit b_552arxd_full;


#define uc_552b_buf_len  32
xdata unsigned char uc_552btxd_buf[uc_552_buf_size*2];
xdata unsigned char uc_552brxd_buf[uc_552_buf_size];
idata unsigned char uc_552btxd_out,uc_552btxd_in;
idata unsigned char uc_552brxd_out,uc_552brxd_in;
bit b_552btxd_done;
bit b_552brxd_full;

//有些中断标记在读取中断寄存器后会被自动清除,所以定义变量来暂存中断向量
//ps:这几个变量可以定义为局部变量,这里为了方便定义为全局变量^_^
unsigned char bdata uc_status_552aisr;
sbit b_552aisr_id = uc_status_552aisr^0;

unsigned char bdata uc_status_552bisr;
sbit b_552bisr_id = uc_status_552bisr^0;

#define xt_552_mhz  1.8432
#define bps_552a 1200
#define bps_552b 9600
#define dl_552a (unsigned int)(xt_552_mhz*1000000/16/bps_552a) //分频系数
计算
#define dl_552B (unsigned int)(xt_552_mhz*1000000/16/bps_552b)
/**********************************************************************
*
* 名称:  v_init_552uart
* 说明:  
* 功能:  初始化552串口
* 调用:  none
* 输入:  none
* 返回值:  none
*
***********************************************************************/

void v_init_552uart(void)
{
//串口1设置
uc_552a_lcr = 0x80; // 使能波特率设置
uc_552a_dll = dl_552a%256; // 设置通讯波特率为1200
uc_552a_dlm = dl_552a/256;
uc_552a_fcr = 0x00; //禁止FIFO模式
uc_552a_lcr = 0x03; // 8 bit_data, 1 bit_stop, no parity
uc_552a_ier = 0x00; // 使能接收和发送中断03
uc_552a_mcr = 0x08; // 使能串口中断

//缓冲区指针初始化
uc_552atxd_out=0;uc_552atxd_in=1;
uc_552arxd_out=uc_552arxd_in=0;


//串口2设置
uc_552b_lcr = 0x80; // 使能波特率设置
uc_552b_dll = dl_552b%256; // 设置通讯波特率为9600
uc_552b_dlm = dl_552b/256;
uc_552b_fcr = 0x8f; //FIFO模式  10001111
uc_552b_lcr = 0x03; // 8 bit_data, 1 bit_stop, no parity
uc_552b_ier = 0x0b; // 使能接收和发送中断03,mcr中断
uc_552b_mcr = 0x08; // 使能串口中断

//缓冲区指针初始化
uc_552btxd_out=0;uc_552btxd_in=1;
uc_552brxd_out=uc_552brxd_in=0;

//并口设置
uc_552_iosel  = 0x55; //全部设置为输出
uc_552_con = 0x00;
uc_552_pr = 0xff; //输出全部为高电平


EX0=1;
EA=1;
}


/**********************************************************************
*
* 名称:  v_sent_552bstr
* 说明:  
* 功能:  发送多个字节
* 调用:  none
* 输入:  str 为要发送的字符串;str_len为字节数;
* 返回值:  none
*
***********************************************************************/

void v_sent_552bstr(unsigned char *str,unsigned char str_len)
{

unsigned char i;

if(str_len==0)
str_len=strlen(str);
for(i=0;i&lt;str_len;i++)
{
uc_552btxd_buf<i>=*str;
str++;
}
uc_552btxd_in=str_len;
uc_552btxd_out=0;
b_552btxd_done=0;


uc_552b_thr=uc_552btxd_buf[uc_552btxd_out];
uc_552btxd_out++;
}






/**********************************************************************
*
* 名称:  ir_552_interrupt
* 说明:  
* 功能:  552的中断处理函数
* 调用:  none
* 输入:  none
* 返回值:  none
*
***********************************************************************/
/* ISR定义:
值 模式 优先级 定义(中断源)
01 16c450 x 没有中断
06 16c450 1 LSR(接收线路状态寄存器)
04 16c450 2 RXRDY(接收中断)
0C 16c450 2 RXRDY(接收超时中断)
02 16c450 3 TXRDY(发送寄存器空)
00 16c450 4 MSR(Modem状态寄存器)

C1 FIFO x 没有中断
C6 FIFO 1 LSR(接收线路状态寄存器)
C4 FIFO 2 RXRDY(接收中断)FIFO超出
预定水平
CC FIFO 2 RXRDY(接收超时中断)
C2 FIFO 3 TXRDY(发送寄存器空)
C0 FIFO 4 MSR(Modem状态寄存器)
*/
void ir_552_interrupt(void) interrupt 0
{
unsigned char i,j;
uc_status_552aisr  = uc_552a_isr;
uc_status_552bisr  = uc_552b_isr;
if(b_552aisr_id &amp;&amp; b_552bisr_id)  return;

if(!b_552aisr_id)
{
//这里是串口a的中断处理程序
}

if(b_552bisr_id) return;
switch(uc_status_552bisr)
{
case 0x01:
break;
case 0x06:
case 0xc6:
i=uc_552b_lsr; //清除中断
//处理代码
break;
case 0x04:
    case 0x0c:
if(!b_552brxd_full)
//缓冲区未满
{
while((uc_552b_lsr &amp; 0x01) == 0 );
//【这里最好加一个超时跳出的条件,以
免因芯片原因陷入死循环】
                                          //以下其他的循环检测也同理需加上跳出条

uc_552brxd_buf[uc_552brxd_in]
=uc_552b_rhr;
  uc_552brxd_in = ++ uc_552brxd_in &amp;
(uc_552b_buf_len-1);
if(uc_552brxd_in == uc_552brxd_out)
b_552brxd_full=1;
else  b_552brxd_full=0;
}
else
//缓冲区已满
{

if(uc_552brxd_in != uc_552brxd_out)
//在上个字节接收后有读取过
{

while((uc_552b_lsr &amp;
0x01) == 0 );
uc_552brxd_buf
[uc_552brxd_in]=uc_552b_rhr;
uc_552brxd_in = ++
uc_552brxd_in &amp; (uc_552b_buf_len-1);
if(uc_552brxd_in ==
uc_552brxd_out) b_552brxd_full=1;
else
b_552brxd_full=0;
}
else
{
while((uc_552b_lsr &amp;
0x01) == 0 );
uc_552brxd_buf
[uc_552brxd_in]=uc_552b_rhr;
  uc_552brxd_in = ++
uc_552brxd_in &amp; (uc_552b_buf_len-1);
uc_552brxd_out = ++
uc_552brxd_out &amp; (uc_552b_buf_len-1);
//将接收缓冲区读指针推一
}

}
break;
case 0x02:
if(uc_552btxd_out == uc_552btxd_in)
{
  b_552btxd_done=1;
for(i=0;i&lt;120;i++)
{
NOP7;
}
// uc_552b_ier = 0x03; // 使
能接收和发送中断03
uc_552b_mcr = 0x08;

}
if(!b_552btxd_done)
         {
while((uc_552b_lsr &amp; 0x20)==0);
uc_552b_thr=uc_552btxd_buf
[uc_552btxd_out];
             uc_552btxd_out++;
}
break;
   case 0x00:
case 0xc0:
i=uc_552b_msr;

if(((i &amp; 0x04)==0x04))// &amp;&amp; ((i &amp; 0x40)==0x40))
//00000100
{

uc_ring_num++;

}
if(uc_ring_num==6)
{
b_ata_need=1;
uc_ring_num=0;
}
break;

case 0xc4: //FIFO 2 RXRDY
(接收中断)FIFO超出预定水平
case 0xcc: //FIFO 2 RXRDY
(接收超时中断)
if(!b_552brxd_full) //缓
冲区未满
{
while((uc_552b_lsr &amp; 0x01) == 0x01 )
{
uc_552brxd_buf
[uc_552brxd_in]=uc_552b_rhr;
  uc_552brxd_in = ++
uc_552brxd_in &amp; (uc_552b_buf_len-1);
if(uc_552brxd_in ==
uc_552brxd_out)
{

b_552brxd_full=1;
break;
}
else  b_552brxd_full=0;
}
}
else
//缓冲区已满
{

if(uc_552brxd_in != uc_552brxd_out)
//在上个字节接收后有读取过
{

while((uc_552b_lsr &amp;
0x01) == 0x01 )
{
uc_552brxd_buf
[uc_552brxd_in]=uc_552b_rhr;
  uc_552brxd_in =
++ uc_552brxd_in &amp; (uc_552b_buf_len-1);
if
(uc_552brxd_in == uc_552brxd_out)
{

b_552brxd_full=1;

break;
}
else  
b_552brxd_full=0;
}
}
else
{
while((uc_552b_lsr &amp;
0x01) == 0 );
uc_552brxd_buf
[uc_552brxd_in]=uc_552b_rhr;
  uc_552brxd_in = ++
uc_552brxd_in &amp; (uc_552b_buf_len-1);
uc_552brxd_out = ++
uc_552brxd_out &amp; (uc_552b_buf_len-1);
//将接收缓冲区读指针推一
}
}
break;
case 0xc2: //FIFO 3 TXRDY
(发送寄存器空)
if(uc_552btxd_out == uc_552btxd_in)
{
  b_552btxd_done=1;
for(i=0;i&lt;120;i++)
{
NOP7;
}
// uc_552b_ier = 0x03; // 使
能接收和发送中断03
uc_552b_mcr = 0x08;

}
if(!b_552btxd_done)
         {
if(((uc_552b_lsr &amp; 0x20)== 0x20) ||
((uc_552b_lsr &amp; 0x10)== 0x10))
{
i=0;
while((uc_552btxd_out &lt;
uc_552btxd_in))
{

uc_552b_thr=uc_552btxd_buf[uc_552btxd_out];
            
uc_552btxd_out++;
i++;
if(i==14)
break;
}
}
}
break;

default:
break;
    }

}
</P>
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|cpubbs论坛. ( 粤ICP备09171248号 )

GMT+8, 2025-4-4 20:03 , Processed in 0.497887 second(s), 7 queries , Gzip On, File On.

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表