搜索
bottom↓
回复: 13

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

[复制链接]

出0入0汤圆

发表于 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[7]={"0"};//串口接收数据缓存
     if(UDR0==0x5a)
     {
          number=0;//包头已经到达
          Recevive_Data_Flag=1;
     }
     if(Recevive_Data_Flag==1)
     {
          Uart_Recevive_Data[number]=UDR0;
          //Uart0_SendByte(UDR0);
          number++;
          //Uart_TXD_String("ok",0);
     }
     //Uart0_SendByte(Recevive_Data_Flag);
     if(number==7)
     {
          SD2405Time.year=Uart_Recevive_Data[1];
          SD2405Time.month=Uart_Recevive_Data[2];
          SD2405Time.day=Uart_Recevive_Data[3];
          SD2405Time.hour=Uart_Recevive_Data[4];
          SD2405Time.minute=Uart_Recevive_Data[5];
          SD2405Time.second=Uart_Recevive_Data[6];
         
          //Recevive_Data_Flag==0;
          SD2405_SetTime();
         
          Uart0_SendByte(Uart_Recevive_Data[0]);
          Uart0_SendByte(Uart_Recevive_Data[1]);
          Uart0_SendByte(Uart_Recevive_Data[2]);
          Uart0_SendByte(Uart_Recevive_Data[3]);
          Uart0_SendByte(Uart_Recevive_Data[4]);
          Uart0_SendByte(Uart_Recevive_Data[5]);
          Uart0_SendByte(Uart_Recevive_Data[6]);
          //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,,请大侠指点啊,,,谢谢

(原文件名:ee.jpg)


(原文件名:未命名.jpg)

出0入0汤圆

发表于 2010-12-4 12:23:06 | 显示全部楼层
把程序到过来不就对上了

出0入90汤圆

发表于 2010-12-4 12:24:27 | 显示全部楼层
这还要指点什么?你肯定是有个变量用来改变一个Buf中对应的buf。一看就知道你这个i没有确保发送完后清零。所以导致每次先发最后一个,再开始正常顺序发送的

出0入0汤圆

 楼主| 发表于 2010-12-5 19:58:51 | 显示全部楼层
回复【2楼】honami520
-----------------------------------------------------------------------
但是我是先判断if(UDR0==0x5a),所以Uart_Recevive_Data[0]=0x5a是没有疑问的啊

出0入0汤圆

发表于 2010-12-5 20:19:34 | 显示全部楼层
那个不一定的,UDRO是个volatile变量, 你第一次比较时已经读过一次,第二次赋值时再读不一定还是这个值,你应该使用一个中间变量用于比较赋值。

出0入0汤圆

 楼主| 发表于 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[7]={"0"};//串口接收数据缓存
     if(UDR0==0x5a)
     {
          number=0;//包头已经到达
          Recevive_Data_Flag=1;
     }  
     if(Recevive_Data_Flag==1)
     {
          Uart_Recevive_Data[number]=UDR0;
          //Uart0_SendByte(UDR0);
          number++;
          //Uart_TXD_String("ok",0);  
     }
     //Uart0_SendByte(Recevive_Data_Flag);  
     if(number==7)
     {
          SD2405Time.year=Uart_Recevive_Data[1];
          SD2405Time.month=Uart_Recevive_Data[2];
          SD2405Time.day=Uart_Recevive_Data[3];
          SD2405Time.hour=Uart_Recevive_Data[4];
          SD2405Time.minute=Uart_Recevive_Data[5];
          SD2405Time.second=Uart_Recevive_Data[6];
           
          //Recevive_Data_Flag==0;
          SD2405_SetTime();
           
          Uart0_SendByte(Uart_Recevive_Data[0]);
          Uart0_SendByte(Uart_Recevive_Data[1]);
          Uart0_SendByte(Uart_Recevive_Data[2]);
          Uart0_SendByte(Uart_Recevive_Data[3]);
          Uart0_SendByte(Uart_Recevive_Data[4]);
          Uart0_SendByte(Uart_Recevive_Data[5]);
          Uart0_SendByte(Uart_Recevive_Data[6]);
          //Uart_TXD_String(Uart_Recevive_Data,0);
          //Uart_TXD_String("ok,you have succeed",0);           
     }
}

出0入0汤圆

 楼主| 发表于 2010-12-5 21:48:34 | 显示全部楼层
回复【4楼】tomhe666 天煞孤星
-----------------------------------------------------------------------

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


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

出0入0汤圆

发表于 2010-12-6 08:24:04 | 显示全部楼层
中断开始unsigned char udr_tmp = UDR0; 以后都使用udr_tmp来操作, UDR0就不要再使用了
另外:你这个中断在接收最后一个数据后, 进行的耗时巨大的发送工作, 建议把发送移到中断外部

出0入0汤圆

 楼主| 发表于 2010-12-6 12:12:08 | 显示全部楼层
回复【7楼】tomhe666 天煞孤星
-----------------------------------------------------------------------

多谢!我试试

出0入0汤圆

 楼主| 发表于 2010-12-6 15:08:30 | 显示全部楼层
回复【7楼】tomhe666 天煞孤星
-----------------------------------------------------------------------

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

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

出0入0汤圆

发表于 2010-12-6 15:38:09 | 显示全部楼层
由于avr的usart有2字节的缓冲,
UDR0做为读功能时, 是串口接收值的读取寄存寄,其值只能读取一次后....你再读,应该读的是另一个缓冲中的内容-_-

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

出0入0汤圆

 楼主| 发表于 2010-12-7 10:22:07 | 显示全部楼层
回复【10楼】snoopyzz
-----------------------------------------------------------------------

讲的很好,谢谢了

读一次,测试结果很正确

出0入0汤圆

发表于 2010-12-7 10:29:06 | 显示全部楼层
串口收发用FIFO队列是个好习惯
头像被屏蔽

出0入0汤圆

发表于 2011-12-15 21:43:36 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-19 22:11

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表