自动产生的串口中断接收程序,支持缓冲区,比较经典的

来源:互联网 发布:imap端口 编辑:程序博客网 时间:2024/06/15 20:48
你的mega128的串口接收程序写的有问题,和什么模块都无关。串口中断是每收到一个字符就会产生一次的,所以你不要看到中断了
就急着处理,收的东西还没全呢,怎么处理啊,要想办法收全了再处理。建议你看看别人的串口接收中断处理代码。
最最最简单的办法,做个延时,等所有的字符都收齐了,再处理。或者开缓冲区,根据缓冲区的长度来判断是否都接收完毕。

下面是用CVAVR自动产生的串口中断接收程序,支持缓冲区,比较经典的:
#include <mega128.h>

#define RXB8 1
#define TXB8 0
#define UPE 2
#define OVR 3
#define FE 4
#define UDRE 5
#define RXC 7

#define FRAMING_ERROR (1<<FE)
#define PARITY_ERROR (1<<UPE)
#define DATA_OVERRUN (1<<OVR)
#define DATA_REGISTER_EMPTY (1<<UDRE)
#define RX_COMPLETE (1<<RXC)

// USART0 Receiver buffer
#define RX_BUFFER_SIZE0 255
char rx_buffer0[RX_BUFFER_SIZE0];

#if RX_BUFFER_SIZE0<256
unsigned char rx_wr_index0,rx_rd_index0,rx_counter0;
#else
unsigned int rx_wr_index0,rx_rd_index0,rx_counter0;
#endif

// This flag is set on USART0 Receiver buffer overflow
bit rx_buffer_overflow0;

// USART0 Receiver interrupt service routine
interrupt [USART0_RXC] void usart0_rx_isr(void)
{
char status,data;
status=UCSR0A;
data=UDR0;
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
{
rx_buffer0[rx_wr_index0]=data;
if (++rx_wr_index0 == RX_BUFFER_SIZE0) rx_wr_index0=0;
if (++rx_counter0 == RX_BUFFER_SIZE0)
{
rx_counter0=0;
rx_buffer_overflow0=1;
};
};
}

#ifndef _DEBUG_TERMINAL_IO_
// Get a character from the USART0 Receiver buffer
#define _ALTERNATE_GETCHAR_
#pragma used+
char getchar(void)
{
char data;
while (rx_counter0==0);
data=rx_buffer0[rx_rd_index0];
if (++rx_rd_index0 == RX_BUFFER_SIZE0) rx_rd_index0=0;
#asm("cli")
--rx_counter0;
#asm("sei")
return data;
}
#pragma used-
#endif

// USART0 Transmitter buffer
#define TX_BUFFER_SIZE0 8
char tx_buffer0[TX_BUFFER_SIZE0];

#if TX_BUFFER_SIZE0<256
unsigned char tx_wr_index0,tx_rd_index0,tx_counter0;
#else
unsigned int tx_wr_index0,tx_rd_index0,tx_counter0;
#endif

// USART0 Transmitter interrupt service routine
interrupt [USART0_TXC] void usart0_tx_isr(void)
{
if (tx_counter0)
{
--tx_counter0;
UDR0=tx_buffer0[tx_rd_index0];
if (++tx_rd_index0 == TX_BUFFER_SIZE0) tx_rd_index0=0;
};
}

#ifndef _DEBUG_TERMINAL_IO_
// Write a character to the USART0 Transmitter buffer
#define _ALTERNATE_PUTCHAR_
#pragma used+
void putchar(char c)
{
while (tx_counter0 == TX_BUFFER_SIZE0);
#asm("cli")
if (tx_counter0 || ((UCSR0A & DATA_REGISTER_EMPTY)==0))
{
tx_buffer0[tx_wr_index0]=c;
if (++tx_wr_index0 == TX_BUFFER_SIZE0) tx_wr_index0=0;
++tx_counter0;
}
else
UDR0=c;
#asm("sei")
}
#pragma used-
#endif
  
回复

举报

  
lwking412
lwking412当前离线
注册时间
2008-4-15
最后登录
2012-3-20
在线时间
0 小时
阅读权限
1
积分
349
帖子
241
精华
0
UID
28812
查看详细资料

54

主题

0

好友

349

积分

游客

莫元
349
  • 发消息
4
发表于 2008-9-2 19:27:55 |只看该作者
好复杂,头都大了,一定要开辟缓冲区么,我直接接收就不可以么?
1做个延时,等所有的字符都收齐了,再处理。 问题是怎么延时呢?可否简单介绍一下
2或者开缓冲区,根据缓冲区的长度来判断是否都接收完毕。 开辟缓冲区我有点思路,可以参考马老师书上的,但是根据缓冲区的长度我还不是很明白这句话,如果我能判断接收完毕后就好了,手机发送的是那么一大串字符!

本身就不是学习编程出身的,老师非让我做这个不做完不行啊!
  
回复

举报

  
lwking412
lwking412当前离线
注册时间
2008-4-15
最后登录
2012-3-20
在线时间
0 小时
阅读权限
1
积分
349
帖子
241
精华
0
UID
28812
查看详细资料

54

主题

0

好友

349

积分

游客

莫元
349
  • 发消息
5
发表于 2008-9-2 19:41:23 |只看该作者
Appcat
你好,可以邮件联系你么,我想知道如何做延时,实在没这方面的经验
希望可以发邮件和你请教!
  
回复

举报

  
Appcat
Appcat当前在线
注册时间
2006-6-25
最后登录
2012-5-31
在线时间
271 小时
阅读权限
90
积分
3844
帖子
3458
精华
5
UID
165346
查看详细资料

68

主题

0

好友

3844

积分

论坛元老

苹果猫

Rank: 8Rank: 8

莫元
3844
  • 发消息
6
发表于 2008-9-2 19:44:08 |只看该作者
手机发送的东西,总要有个上限吧,不可能是无限的吧,所以把你系统需要处理的最长长度+1做为缓冲区长度总可以吧。其实
英文短信才几个字符啊?上面我贴的程序里边开了255个字符,绝对够用了。

仔细看看上面的程序,里边有一个变量rx_counter0,这个就是关键所在。你在主程序里边判断rx_counter0是否不为零,如果
不为零,说明串口已经有东西进来了,计算一下你的波特率和最大长度,做一个延时,保证串口缓冲区能够收到所有字符,然后
取出整个缓冲区,你的完整短信已经在里边了,该怎么处理就怎么处理了。

#define MAX_BUF_LENS 255
unsigned char buf[MAX_BUF_LENS], i

//初始化,首先清空串口缓冲区,防止残留的字符干扰
while (rx_counter0) getchar();
memset(buf, 0, MAX_BUF_LENS);
......................

//自己做循环,检测rx_counter0是否不为零
while (!rx_counter0);
//延时100毫秒,具体多少需要自己算,这个时间宜长不宜短
delay_ms(100);
i = 0;
while (rx_counter0)
{
buf = getchar();
i++;
}
//到这里,串口过来的短信已经完整的存放在buf中了,你可以对buf进行需要的操作了
原创粉丝点击