16C550在51系统中的应用--C51例程
<P>16C550在51系统中的应用--C51例程作者:adlion
</P>
<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_base0xc000
//这里定义地址,具体的地址定义要看系统连接了
//串口1
#define uc_552a_thrXBYTE // Transmit Holding
Register
#define uc_552a_rhrXBYTE // Receive Holding
Register
#define uc_552a_ierXBYTE // Interrupt Enable
Register
#define uc_552a_isrXBYTE // Interrupt Status
Register
#define uc_552a_fcrXBYTE // FIFO control register
#define uc_552a_lcrXBYTE // Line control Register
#define uc_552a_mcrXBYTE // Modem Control Register
#define uc_552a_lsrXBYTE // Line Status Register
#define uc_552a_msrXBYTE // Modem Status Register
#define uc_552a_sprXBYTE // Scratchpad Register
#define uc_552a_dllXBYTE
#define uc_552a_dlmXBYTE
//串口2
#define uc_552b_thrXBYTE // Transmit Holding
Register
#define uc_552b_rhrXBYTE // Receive Holding
Register
#define uc_552b_ierXBYTE // Interrupt Enable
Register
#define uc_552b_isrXBYTE // Interrupt Status
Register
#define uc_552b_fcrXBYTE // FIFO control register
#define uc_552b_lcrXBYTE // Line control Register
#define uc_552b_mcrXBYTE // Modem Control Register
#define uc_552b_lsrXBYTE // Line Status Register
#define uc_552b_msrXBYTE // Modem Status Register
#define uc_552b_sprXBYTE // Scratchpad Register
#define uc_552b_dllXBYTE
#define uc_552b_dlmXBYTE
//并口
#define uc_552_pr XBYTE // Port Register
#define uc_552_iosel XBYTE // I/O Select Register
#define uc_552_sr XBYTE // Status Register
#define uc_552_com XBYTE // Command Register
#define uc_552_con XBYTE // Control Register
//缓冲区
#define uc_552a_buf_len64
xdata unsigned char uc_552atxd_buf;
xdata unsigned char uc_552arxd_buf;
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_len32
xdata unsigned char uc_552btxd_buf;
xdata unsigned char uc_552brxd_buf;
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_mhz1.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<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++;
}
/**********************************************************************
*
* 名称: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 && 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 & 0x01) == 0 );
//【这里最好加一个超时跳出的条件,以
免因芯片原因陷入死循环】
//以下其他的循环检测也同理需加上跳出条
件
uc_552brxd_buf
=uc_552b_rhr;
uc_552brxd_in = ++ uc_552brxd_in &
(uc_552b_buf_len-1);
if(uc_552brxd_in == uc_552brxd_out)
b_552brxd_full=1;
elseb_552brxd_full=0;
}
else
//缓冲区已满
{
if(uc_552brxd_in != uc_552brxd_out)
//在上个字节接收后有读取过
{
while((uc_552b_lsr &
0x01) == 0 );
uc_552brxd_buf
=uc_552b_rhr;
uc_552brxd_in = ++
uc_552brxd_in & (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 &
0x01) == 0 );
uc_552brxd_buf
=uc_552b_rhr;
uc_552brxd_in = ++
uc_552brxd_in & (uc_552b_buf_len-1);
uc_552brxd_out = ++
uc_552brxd_out & (uc_552b_buf_len-1);
//将接收缓冲区读指针推一
}
}
break;
case 0x02:
if(uc_552btxd_out == uc_552btxd_in)
{
b_552btxd_done=1;
for(i=0;i<120;i++)
{
NOP7;
}
// uc_552b_ier = 0x03; // 使
能接收和发送中断03
uc_552b_mcr = 0x08;
}
if(!b_552btxd_done)
{
while((uc_552b_lsr & 0x20)==0);
uc_552b_thr=uc_552btxd_buf
;
uc_552btxd_out++;
}
break;
case 0x00:
case 0xc0:
i=uc_552b_msr;
if(((i & 0x04)==0x04))// && ((i & 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 & 0x01) == 0x01 )
{
uc_552brxd_buf
=uc_552b_rhr;
uc_552brxd_in = ++
uc_552brxd_in & (uc_552b_buf_len-1);
if(uc_552brxd_in ==
uc_552brxd_out)
{
b_552brxd_full=1;
break;
}
elseb_552brxd_full=0;
}
}
else
//缓冲区已满
{
if(uc_552brxd_in != uc_552brxd_out)
//在上个字节接收后有读取过
{
while((uc_552b_lsr &
0x01) == 0x01 )
{
uc_552brxd_buf
=uc_552b_rhr;
uc_552brxd_in =
++ uc_552brxd_in & (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 &
0x01) == 0 );
uc_552brxd_buf
=uc_552b_rhr;
uc_552brxd_in = ++
uc_552brxd_in & (uc_552b_buf_len-1);
uc_552brxd_out = ++
uc_552brxd_out & (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<120;i++)
{
NOP7;
}
// uc_552b_ier = 0x03; // 使
能接收和发送中断03
uc_552b_mcr = 0x08;
}
if(!b_552btxd_done)
{
if(((uc_552b_lsr & 0x20)== 0x20) ||
((uc_552b_lsr & 0x10)== 0x10))
{
i=0;
while((uc_552btxd_out <
uc_552btxd_in))
{
uc_552b_thr=uc_552btxd_buf;
uc_552btxd_out++;
i++;
if(i==14)
break;
}
}
}
break;
default:
break;
}
}
</P>
页:
[1]