求c8051F020的UART串口通信程序

求c8051F020的UART串口通信程序,第1张

//摘要: 掌握 UART0配置及使用,程序中将UART0 配置到P0.0、 P0.1。利用串口调试助手,波特率设置为4800,并选择十六进制发送和显示,十六进制发送为偶数个,不然会少返回一个数,详见程序注释。

#include "c8051f020.h"

unsigned char data1

void SYSCLK_Init()

void PORT_Init()

void UART0_Init()

void SYSCLK_Init()

{

unsigned int i

OSCXCN=0X67//0X67=0110,0111

for(i=0i<256i++)//等待>1ms

while(!(OSCXCN&0X80)) //等待XTLVLD变为1

OSCICN=0X88//时钟失效监测器,选择外部时钟源作为系统时钟

}

void PORT_Init()

{

XBR0 = 0x27/*交叉开关配置,URAT总线TX0置到P0.0口,RX0置到P0.1口, SPI总线SCK配置到P0.2口,

MOSI为P0.4口, NSS为P0.5,MISO配置到P0.3口,IIC总线SDA置到P0.6口�SCK置到P0.7 TX1,RX1配置到P1.0,P1.1,CEX0,CEX1,配置到P1.2,P1.3,外部中断int0配置到P1.4 */

XBR1 = 0x04

XBR2 = 0x44 /*允许功能选择开关有效*/

P0MDOUT = 0x1A/*SCK、MOSI和NSS为推拉式输出,MISO为开漏式.*/

P74OUT =0xff

}

void UART0_Init()

{

SCON0=0x50 //串口方式1

TMOD=0X20//选用定时器1作为波特率发生器

TH1=0xF4 //波特率为4800

TL1=0xF4

ES0=1 //开启串口中断0

TF1=0

TR1=1 //定时器启动

PCON=0X80//波特率加倍 波特率为9600

TI0=1

}

void UART0_ISR() interrupt 4 using 1

{

if(RI0)

{

RI0=0//中断接收标志清零

data1=SBUF0//接收数据

SBUF0=data1//发送数据

while(TI0==0)

TI0=0//发送标志清零

}

}

main()

{

WDTCN=0XDE

WDTCN=0XAD

SYSCLK_Init()

PORT_Init()

UART0_Init()

EA=1

while(1)

}

#include<pic.h>//包含单片机内部资源预定义

#ifndef uchar

#define uchar unsigned char

#define uint unsigned int

#endif

//__CONFIG(0x2129)

bit rec_flag //串口中断标志位,有串口中断,置1

uchar uartdata //串口数据保存到此位置中

void Uart_char(uchar dat)//串口发送一个数据

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

函数原型:void main(void)

功能:等待串口发送中断到来,将接收到的设计再通过串口发回

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

void main(void)

{

TRISB1=1

TRISB2=1

SPBRG=0X19 //设置波特率为9600BPS

TXSTA=0X24 //使能串口发送,选择高速波特率

RCSTA=0X90 //使能串口工作,连续接收

RCIE=0X1 //使能接收中断

GIE=0X1 //开放全局中断

PEIE=0X1 //使能外部中断

//INTCON=0X00

/* while(1) //查询模式下

{

RCIE=1

while(RCIF==0)

RCIE=0

Send_char(RCREG)

}

*/

while(1) //中断模式下,等待中断的到来

{

if(rec_flag==1) //如果接收中断到来

{

rec_flag=0//接收标志清零

Uart_char(uartdata)//将接收来的数据发送到串口

}

}

}

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

函数原型:void Uart_char(uchar dat)

功能:将dat数据通过串口传送出去

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

void Uart_char(uchar dat)

{

TXREG=dat //将dat数据存入TXREG

// TXEN=1 //启动发送,TSR开始移位 *** 作。

while (TRMT==0) //判断是否TSR发送完毕,未完等待。

// TXEN=0 //关发送功能,防止TXREG空时,TXIF产生置位

}

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

函数原型:void interrupt usart(void)

功能:串口接收到数据,接受发来的数据将接

收到数据标志位rec_flag置1

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

void interrupt usart(void)

{

if(RCIF) //判断是否为串口接收中断

{

rec_flag = 1

//RCIF=0

uartdata = RCREG// 接收数据并存储

//TXREG=recdata //把接收到的数据发送回去

}

}

这段程序应该对你有用

中断方式下进行串口通讯的正确方法

一般普遍的把串口通讯分为查询方式和中断方式。查询方式比较容易理解,各种书籍上都介绍的比较清楚。但中断方式,没有几本书讲得好的,甚至有些例程根本无法实际应用。

问题有:

1,半中断法。只使用接收中断,不使用发送中断,发送时还是依靠查询中断标志的办法;如下: ES = 0//若是接收使用中断方式,某些单片机需要关中断。但C51不一定需要。这里只是示例。 SBUF = needsendcharWhile (!TI)TI = 0ES = 1 这里的问题是:发送数据时需要等待数据发完才能继续其他工作,程序效率降低;发送时需要关中断,影响数据接收。

2,接收中断的处理方法错误。如下: 中断程序: void ser() interrupt 4 { RI = 0 temp = SBUF//读走数据,放入缓存(全局的)变量 rx_flag = 1//设置接收标志 } 主程序: void main(){ „//初始化 While (1) {If (rx_flag ==1){//查询接收标志 rx_flag = 0//清楚接收标志 x = temp//从暂存变量读取数据 „//接收处理 }„//其它 *** 作 } } 这里的问题是:如果串口接收数据的间隔时间小于“接收处理”和“其它 *** 作”所用的时间时,接收数据会丢失一部分。 正确使用中断方式处理串口收发应达到以下目的: 1,完全使用中断控制接收和发送,以达到最快的收发速度。 2,接收和发送互不影响,达到全双工通讯效果。

3,应用程序不发生等待,以达到最高运行效率。

undefined

正确的中断发送方法如下:

1,建立一个足够大小的环形发送缓冲区,建立一个信号量(用于指示发送的数据量),建立一个发送标志位(用于指示发送状态)。

2,应用程序将数据写入环形发送缓冲区,查询发送接收标志,若不在发送状态,手动触发中断。

3,产生发送中断时,查询信号量,以判别发送缓冲区内是否有数据;若有,置发送标志位,从缓冲区读取数据发送,累减信号量;若无,清除发送标志位。 C51的例程如下:

//变量定义 #define BUF_SIZE 0x10//环形收发缓冲区长度 //发送参数 char tx_circbuf[BUF_SIZE]//环形发送缓冲区 uint8 tx_sem//信号量 bool tx_run//发送标志位 uint8 tx_circin//进环形缓冲区的位置指示 uint8 tx_circout//出环形缓冲区的位置指示 //发送初始化程序 void tx_init(void){ //硬件初始化 略 //发送参数初始化 tx_sem = 0 tx_run = Falsetx_circin = 0tx_circout = 0} //中断程序 void tx_int(void) interrupt 4 { if (TI){ TI = 0 if (tx_sem){SBUF = tx_circbuf [tx_circout]// 发送缓冲区中的字符 if (++tx_circout >= BUF_SIZE) tx_circout = 0 tx_sem--//累减信号量tx_run = True//置发送标志位 } else tx_run = False//清除发送标志位 } } //发送处理程序,由应用程序调用 //输入:发送数据指针,发送数据长度

void tx_data(char * txbuf,uint8 len){ while (len){ tx_circbuf [tx_circin] = *txbuf++// 存入数据到发送缓冲区 if (++tx_circin >= BUF_SIZE) tx_circin = 0tx_sem++//累减信号量 len-- if (tx_run == False)TI=1//查询发送状态标志。若发送空闲,触发中断,发送数据的工作由中断程序自动完成。 } }正确的中断接收方法如下:

1,建立一个足够大小的环形接收缓冲区,建立一个信号量(用于指示接收的数据量)。

2,发生接收中断时,读出字节放入接收缓冲区,并累加信号量。

3,应用程序查询接收标志,如信号量不为0,则从接收缓冲区读取数据进行处理,累减信号量。 C51的例程如下: //变量定义 #define BUF_SIZE 0x10//环形收发缓冲区长度 //接收参数 char rx_circbuf[BUF_SIZE]// 环形接收缓冲区 uint8 rx_sem// 信号量 uint8 rx_circin//进环形缓冲区的位置指示 uint8 rx_circout//出环形缓冲区的位置指示 //接收初始化程序 void rx_init(void){ //硬件初始化 略 //接收参数初始化 rx_sem = 0rx_circin = 0rx_circout = 0} //中断程序 void rx_int(void) interrupt 4 { if (RI){ RI = 0 rx_circbuf [rx_circin] = SBUF// 读出字节放入接收缓冲区 if (++rx_circin >= BUF_SIZE) rx_circin = 0rx_sem++//累加信号量


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/11833733.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-19
下一篇 2023-05-19

发表评论

登录后才能评论

评论列表(0条)

保存