⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serial.c

📁 MEGA32L 单片机的按键,LED,LCD等测试例程,ICCAVR编译器
💻 C
字号:
//======================================
//串口模块源程序
//FileName =serial.c
//Date Time=20071214...20071215
//======================================
#include "serial.h"
#include "string.h"

/*
	使用中断方式进行通讯!
*/

volatile struct	_st_serial_buff st_serial_buff;	//串口操作缓冲结构


//XCK/T0/PB0	不使用
//RXD/PD0	接收数据引脚
//TXD/PD1	发送数据引脚
//--------------------------------------
//	HD_SERIAL_S01
//功能:
//	初始化串口(查询方式),9600,8,1,n
//输入:
//	无
//输出:
//	无
//--------------------------------------
void rs232_init_sets(void)
{
	UBRRH =(uchar)(CONST_INT_UBRR_SETS >>8) &0x7f;
	UBRRL =(uchar)(CONST_INT_UBRR_SETS &0xff);
	UCSRA =(uchar)(CONST_BYTE_UCSRA);
	UCSRB =(uchar)(CONST_BYTE_UCSRB);
	UCSRC =(uchar)(CONST_BYTE_UCSRC);

	//接收参数初始化	
	st_serial_buff.p_recv_start =0;		//起始存储指针
	st_serial_buff.p_recv_end =0;		//结束存储指针
	st_serial_buff.rlen_needed =0;		//需要的接收长度(<=接收缓冲的长度)
	st_serial_buff.rlen_acted =0;		//实际的接收长度	
}


//----------------------------------------------
//接收指定长度的数据串
//输入:
//	r_str		存储接收数据的指针
//	r_len		需要接收的长度
//输出:
//	实际接收的字节数
//----------------------------------------------
uchar	rs232_recv_str(uchar *r_str, uchar r_len)
{
uchar i;
	st_serial_buff.rlen_acted =0;
	st_serial_buff.rlen_needed =r_len;
	//必要时这里可以添加接收超时判断,退出
	while(st_serial_buff.rlen_acted <r_len);
	
	for(i=0; i<st_serial_buff.rlen_acted; i++)
	{
		*(r_str +i) =st_serial_buff.recv[st_serial_buff.p_recv_start];
		if(++st_serial_buff.p_recv_start >=CONST_RECV_BUFF_LEN_MAX)
		{
			st_serial_buff.p_recv_start =0;
		}
	}
	st_serial_buff.rlen_needed =0;
	st_serial_buff.rlen_acted =0;
	return(i);	
}


//----------------------------------------------
//指定长度的数据串发送
//输入:
//	s_str		发送数据指针
//	s_len		发送长度
//输出:
//	无
//----------------------------------------------
void	rs232_send_str(uchar *s_str, uchar s_len)
{
	memcpy((uchar *)&st_serial_buff.send[0], s_str, s_len);
	st_serial_buff.tx_pos_start =1;
	st_serial_buff.slen_needed =s_len;
	UDR =st_serial_buff.send[0];		//启动中断方式的发送
	UCSRB |=BIT(UDRIE);			//因为UDRIE中断回自我关断,以减少CPU负荷
	while((UCSRB &BIT(UDRIE)) !=0);		//等待发送完毕
}

//======================================
//以下是中断模式的函数,需要外部打开‘I’
//======================================
//接收中断接口函数
//输入:
//	st_serial_buff.rlen_needed 需要接收的长度
//输出:
//	st_serial_buff.recv[]
//	st_serial_buff.rlen_acted
//注意:
//	一般设置st_serial_buff.rlen_needed =0 不接收, !=0(<=缓冲长度)接收定长字节,
void	_irq_serial_rx_server(void)
{
uchar sreg_bak;
	sreg_bak =SREG;
	
	if(!(UCSRA & BIT(FE)) && !(UCSRA & BIT(DOR)) )
	{	
		if(st_serial_buff.rlen_acted <st_serial_buff.rlen_needed)
		{
			//中断标志读取后自动清除		
			st_serial_buff.recv[st_serial_buff.p_recv_end] =UDR;
			st_serial_buff.rlen_acted ++;
			if(++st_serial_buff.p_recv_end >=CONST_RECV_BUFF_LEN_MAX)
			{
				st_serial_buff.p_recv_end =0;
			}			
			SREG =sreg_bak;
			return;
		}		
	}

	//仅仅是清除RX中断标志
	if(UDR ==0){};	
	
	SREG =sreg_bak;
}


//发送缓存空中断接口函数
//输入:
//	st_serial_buff.slen_needed
//	st_serial_buff.tx_pos_start
//	st_serial_buff.send[]
void	_irq_serial_udre_server(void)
{
uchar sreg_bak;
	sreg_bak =SREG;

	if( (st_serial_buff.slen_needed !=0) && (st_serial_buff.tx_pos_start <st_serial_buff.slen_needed) )
	{
		UDR =st_serial_buff.send[st_serial_buff.tx_pos_start++];
	}
	else
	{	//关闭中断
		UCSRB &= ~BIT(UDRIE);
	}
	
	SREG =sreg_bak;
}


//发送完毕中断接口函数
//执行结束自动清除中断标志
//输出:
//	st_serial_buff.slen_needed
void	_irq_serial_tx_server(void)
{
uchar sreg_bak;
	sreg_bak =SREG;

	st_serial_buff.slen_needed =0;

	SREG =sreg_bak;
}

//End Of File

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -