打印
[AVR单片机]

MAGE16 串口通信 的问题

[复制链接]
3133|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
phctgu|  楼主 | 2009-11-13 17:42 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 phctgu 于 2009-11-17 15:29 编辑

本人刚刚接触AVR单片机,自己做了个USART通信,目的是两个单片机之间进行数据传输,但是好像没有反应,希望请教高手,到底我是哪里错了,在此先谢谢朋友们.

   晶振我用的是内部RC   4M,波特率设置的是 9600,目的只是希望A(U1)单片机发数据
给B(U2)单片机,如果B单片机收到数据后,点亮LED灯;两个单片机烧写的程序是一样的
   其中 触发数据传输开始 我是直接把 PC0接地。


#include<iom16v.h>
#include<macros.h>
#define uchar unsigned char
#define uint  unsigned int
uchar rx_num;

void ini_port(void)
{ DDRA|=(1<<DDA0)|(1<<DDA1);
   PORTA|=(1<<PA0)|(1<<PA1);  
   DDRC=0x00;
   PORTC|=(1<<PC0)|(1<<PC1);  
}
  void ini_usart(void)
  {
   UCSRA=0x00;
   UBRRH=0x00;
   UBRRL=0x19;  // SET BAUD IN 9600
   UCSRC|=(1<<UCSZ1)|(1<<UCSZ0); // SET BIT OF DATA
   UCSRB|=(1<<RXEN)|(1<<TXEN)|(1<<RXCIE); // ENABLE SEND AND RECEIVE   
  }
   void send_t(uchar urt)
   {
    UDR=urt;
while(!(UCSRA&(1<<UDRE))); // WAITING FOR SEND
UCSRA|=(1<<UDRE);          // SEND OVER
   }
  
  #pragma interupt_handler USART_RX:12
  void USART_RX(void)
  {
   CLI();
   rx_num=UDR;
   while(!(UCSRA&(1<<UDRE)));
   UCSRA|=(1<<UDRE);
   SEI();  
  }  

/////////////////////////////////
void main()
{
   ini_port();
   ini_usart();
   SEI();
   while(1)
   {
   if(rx_num==0x55)   
   {
     PORTA&=~(1<<PA0);
   }
   else if((PINC&0x01)==0x00)
   {
     send_t(0x55);
     PORTA^=(1<<PA0);
   }
   }
}

usart.jpg (102.45 KB )

usart.jpg

相关帖子

沙发
chen3bing| | 2009-11-13 17:49 | 只看该作者
你那个LED是不会亮的,用LED-YELLOW,RED,或者GREEN。

使用特权

评论回复
板凳
cwei8545| | 2009-11-13 20:13 | 只看该作者
怎么只有一个程序,两个都跑的一样的程序?
两个单片机通讯的一个做主一个从,两个的设置都不一样,

使用特权

评论回复
地板
电脑圆圆| | 2009-11-14 08:12 | 只看该作者
1)波特率是不是这样计算的:4000000/9600/16=26=0x1A
2)熔丝烧了没?有的avr默认用的是内部rc震荡,用外部石英晶振还需烧写熔丝
3)
#pragma interupt_handler USART_RX:12
  void USART_RX(void)
  {
   CLI();           //进入中断时自动屏蔽中断,无需你清了,建议不要写了
   rx_num=UDR;
   while(!(UCSRA&(1<<UDRE))) //进入接收中断本来就已经收到,无需等,建议不要写了
UCSRA|=(1<<UDRE);;// 进入中断自动清除,建议不要写了

   SEI();  //退出中断自动置位,建议不要写了
  }  

#pragma interupt_handler USART_RX:12
  void USART_RX(void)
{}
这种写法貌似n年前的版本,现在都是
#pragma vector=USART_vect
__interrupt void USART_INT()
{}
建议用新版本编译器,不过应该跟编译器没关系

使用特权

评论回复
5
电脑圆圆| | 2009-11-14 08:18 | 只看该作者
补充一条:
在main函数里没有延迟,rx_num也不清零,即使收到了led闪烁的频率也在百千级别你是看不出来

使用特权

评论回复
6
phctgu|  楼主 | 2009-11-14 10:51 | 只看该作者
4# 电脑圆圆

在这里要非常感谢 电脑圆圆 朋友的指教,还有点不是很清楚,因为我最初是用51的,也看过很多别人的例子,在中断里
   while(!(UCSRA&(1<<UDRE)));
   UCSRA|=(1<<UDRE);
   SEI();
这些都是用了的啊,发送数据不需要像51那样要 等待发送完毕吗

使用特权

评论回复
7
phctgu|  楼主 | 2009-11-14 10:59 | 只看该作者
5# 电脑圆圆

我把接收的单片机程序改了下,只要接受的正确  就点亮LED, 好像还是不行啊

使用特权

评论回复
8
杜专| | 2009-11-14 16:05 | 只看该作者
我也在学习

使用特权

评论回复
9
phctgu|  楼主 | 2009-11-16 16:47 | 只看该作者
问题还没有解决啊,不知道到底出在哪?????

使用特权

评论回复
10
maomao2126| | 2009-11-18 12:07 | 只看该作者
可以先用串口调试工具,分别调通接收与发送再去实验

使用特权

评论回复
11
maomao2126| | 2009-11-18 12:08 | 只看该作者
哦,搞错了
是仿真的哦

使用特权

评论回复
12
maomao2126| | 2009-11-18 12:26 | 只看该作者
刚看了一下程序,是不是在写UCSRC bit7没有置起来的缘故
因为该寄存器是和其他的寄存器是复用的
  void send_t(uchar urt)
   {
    UDR=urt;
while(!(UCSRA&(1<<UDRE))); // WAITING FOR SEND  //是不是应该先判断啊
UCSRA|=(1<<UDRE);          // SEND OVER
   }

使用特权

评论回复
13
phctgu|  楼主 | 2009-11-19 17:11 | 只看该作者
发送的都是正常的 ,就是接受不到,不知道什么原因

使用特权

评论回复
14
wangwo| | 2009-11-19 20:36 | 只看该作者
内容挺丰富的

使用特权

评论回复
15
lvg2020| | 2009-12-9 11:17 | 只看该作者
新手,顶一下。

使用特权

评论回复
16
woshixinshou| | 2010-3-6 21:03 | 只看该作者
不知道仿真的会不会跟那个内部RC振荡器的误差有关,实物使用中,对时序要求比较高的功能,都不建议使用内部振荡器。

使用特权

评论回复
17
gsk1201| | 2011-8-24 01:35 | 只看该作者
LZ说的好

使用特权

评论回复
18
joyme| | 2011-8-24 09:18 | 只看该作者
  while(!(UCSRA&(1<<UDRE)));
   UCSRA|=(1<<UDRE);

这语句肯定是有问题
第一:应该是 UCSRA &= ~(1<<UDRE)即清除中断标志
第二:这可以用在非中断的发送接收,而不是在中断中用,读取UDR时MCU自动清除了此标志,你的程序很可能一直停在while(!(UCSRA&(1<<UDRE))); 因为这个标志已经被清除了
如果可以仿真的话你可以试试

使用特权

评论回复
19
lisijun100| | 2011-8-26 04:21 | 只看该作者
楼主 实验一下 中断,不要用死循环等待!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

19

主题

68

帖子

1

粉丝