guxingganyue 发表于 2010-12-4 11:59:19

太奇怪了,串口发数居然不按我的意思发,它倒着发,,,,请大侠指点

//ICC-AVR application builder : 2010-10-11 14:28:07
// Target : M48
// Crystal: 7.3728Mhz
/*----------------------------------
#ifndef _Uart_h_
#define _Uart_h_
#include ".\head\SD2405.h"

//晶振和波特率
#define Fosc_CPU 7372800
#define Baud 9600

void Init_Uart0();
void Uart0_SendByte(uint8 u8_Data);
uint8 Uart_getchar();
void Uart_TXD_String(char *str,uint8 Enter);

//UART初始化函数
void Init_Uart0()
{   
    //允许收发打开接收中断
    UCSR0B=(1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0);
    UBRR0L=((Fosc_CPU/16/Baud)-1)%256;//设置波特率寄存器
    UBRR0H=((Fosc_CPU/16/Baud)-1)/256;
    UCSR0C=(1<<UCSZ01)|(1<<UCSZ00);//8位数据+1位STOP
}
//字符输出
void Uart0_SendByte(uint8 u8_Data)
{
   while(!(UCSR0A&(1<<UDRE0)));//上次发送有没有完成
   UDR0=u8_Data;
}
//字符输入
uint8 Uart_getchar()
{
   while(!(UCSR0A&(1<<RXC0)));//有没有接收到数据
   return UDR0;
}
//*****************串口发送字符串******************************
// 入口参数:   *str:字符串首地址
//                  ENTER:(回车换行) 1:不换行0:换行
// 出口参数:   无
// 函数功能:   从串口发送一字符串
//*************************************************************
void Uart_TXD_String(char *str,uint8 Enter)
{
    while( *str )
    {
         Uart0_SendByte(*str);
         str++;
    }
    if(Enter==0)
    {   
      Uart0_SendByte(0x0D);   
      Uart0_SendByte(0x0A);   
    }
}
#pragma interrupt_handler uart0_rx_isr:19
void uart0_rx_isr(void)
{
   //uart has received a character in UDR0
   static uint8 number;
   static uint8 Recevive_Data_Flag;//串口接收数据标志
   static uint8 Uart_Recevive_Data={"0"};//串口接收数据缓存
   if(UDR0==0x5a)
   {
          number=0;//包头已经到达
          Recevive_Data_Flag=1;
   }
   if(Recevive_Data_Flag==1)
   {
          Uart_Recevive_Data=UDR0;
          //Uart0_SendByte(UDR0);
          number++;
          //Uart_TXD_String("ok",0);
   }
   //Uart0_SendByte(Recevive_Data_Flag);
   if(number==7)
   {
          SD2405Time.year=Uart_Recevive_Data;
          SD2405Time.month=Uart_Recevive_Data;
          SD2405Time.day=Uart_Recevive_Data;
          SD2405Time.hour=Uart_Recevive_Data;
          SD2405Time.minute=Uart_Recevive_Data;
          SD2405Time.second=Uart_Recevive_Data;
         
          //Recevive_Data_Flag==0;
          SD2405_SetTime();
         
          Uart0_SendByte(Uart_Recevive_Data);
          Uart0_SendByte(Uart_Recevive_Data);
          Uart0_SendByte(Uart_Recevive_Data);
          Uart0_SendByte(Uart_Recevive_Data);
          Uart0_SendByte(Uart_Recevive_Data);
          Uart0_SendByte(Uart_Recevive_Data);
          Uart0_SendByte(Uart_Recevive_Data);
          //Uart_TXD_String(Uart_Recevive_Data,0);
          //Uart_TXD_String("ok,you have succeed",0);         
   }
}
#endif

如我发:5a 10 12 04 12 33 45 应该回5a 10 12 04 12 33 45 但它回的是45 5a 10 12 04 12 33,,请大侠指点啊,,,谢谢
http://cache.amobbs.com/bbs_upload782111/files_35/ourdev_602213EONHMX.jpg
(原文件名:ee.jpg)

http://cache.amobbs.com/bbs_upload782111/files_35/ourdev_602214QS2T22.jpg
(原文件名:未命名.jpg)

jrcsh 发表于 2010-12-4 12:23:06

把程序到过来不就对上了

honami520 发表于 2010-12-4 12:24:27

这还要指点什么?你肯定是有个变量用来改变一个Buf中对应的buf。一看就知道你这个i没有确保发送完后清零。所以导致每次先发最后一个,再开始正常顺序发送的

guxingganyue 发表于 2010-12-5 19:58:51

回复【2楼】honami520
-----------------------------------------------------------------------
但是我是先判断if(UDR0==0x5a),所以Uart_Recevive_Data=0x5a是没有疑问的啊

tomhe666 发表于 2010-12-5 20:19:34

那个不一定的,UDRO是个volatile变量, 你第一次比较时已经读过一次,第二次赋值时再读不一定还是这个值,你应该使用一个中间变量用于比较赋值。

guxingganyue 发表于 2010-12-5 21:46:10

回复【4楼】tomhe666 天煞孤星
-----------------------------------------------------------------------

下面这个程序在gcc上的结果是对的,但放在icc上不知怎么就不对了
void uart0_rx_isr(void)
{
   //uart has received a character in UDR0
   static uint8 number;
   static uint8 Recevive_Data_Flag;//串口接收数据标志
   static uint8 Uart_Recevive_Data={"0"};//串口接收数据缓存
   if(UDR0==0x5a)
   {
          number=0;//包头已经到达
          Recevive_Data_Flag=1;
   }
   if(Recevive_Data_Flag==1)
   {
          Uart_Recevive_Data=UDR0;
          //Uart0_SendByte(UDR0);
          number++;
          //Uart_TXD_String("ok",0);
   }
   //Uart0_SendByte(Recevive_Data_Flag);
   if(number==7)
   {
          SD2405Time.year=Uart_Recevive_Data;
          SD2405Time.month=Uart_Recevive_Data;
          SD2405Time.day=Uart_Recevive_Data;
          SD2405Time.hour=Uart_Recevive_Data;
          SD2405Time.minute=Uart_Recevive_Data;
          SD2405Time.second=Uart_Recevive_Data;
         
          //Recevive_Data_Flag==0;
          SD2405_SetTime();
         
          Uart0_SendByte(Uart_Recevive_Data);
          Uart0_SendByte(Uart_Recevive_Data);
          Uart0_SendByte(Uart_Recevive_Data);
          Uart0_SendByte(Uart_Recevive_Data);
          Uart0_SendByte(Uart_Recevive_Data);
          Uart0_SendByte(Uart_Recevive_Data);
          Uart0_SendByte(Uart_Recevive_Data);
          //Uart_TXD_String(Uart_Recevive_Data,0);
          //Uart_TXD_String("ok,you have succeed",0);         
   }
}

guxingganyue 发表于 2010-12-5 21:48:34

回复【4楼】tomhe666 天煞孤星
-----------------------------------------------------------------------

你应该使用一个中间变量用于比较赋值????????????????


不懂,能说详细点吗,谢谢

tomhe666 发表于 2010-12-6 08:24:04

中断开始unsigned char udr_tmp = UDR0; 以后都使用udr_tmp来操作, UDR0就不要再使用了
另外:你这个中断在接收最后一个数据后, 进行的耗时巨大的发送工作, 建议把发送移到中断外部

guxingganyue 发表于 2010-12-6 12:12:08

回复【7楼】tomhe666 天煞孤星
-----------------------------------------------------------------------

多谢!我试试

guxingganyue 发表于 2010-12-6 15:08:30

回复【7楼】tomhe666 天煞孤星
-----------------------------------------------------------------------

对谢大哥的指点,按您的意思改过后结果就正确了

但我还有点不太明白这是为什么

snoopyzz 发表于 2010-12-6 15:38:09

由于avr的usart有2字节的缓冲,
UDR0做为读功能时, 是串口接收值的读取寄存寄,其值只能读取一次后....你再读,应该读的是另一个缓冲中的内容-_-

这种寄存器,当然是读一次就好,是常识,不要试图多次读取的说,指望它能一直保持数据多久?

guxingganyue 发表于 2010-12-7 10:22:07

回复【10楼】snoopyzz
-----------------------------------------------------------------------

讲的很好,谢谢了

读一次,测试结果很正确

luoyiming1984 发表于 2010-12-7 10:29:06

串口收发用FIFO队列是个好习惯

taocongrong 发表于 2011-12-15 21:43:36

页: [1]
查看完整版本: 太奇怪了,串口发数居然不按我的意思发,它倒着发,,,,请大侠指点