找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 10260|回复: 5
打印 上一主题 下一主题
收起左侧

关于单片机串口接收一帧数据,收不到数据

[复制链接]
跳转到指定楼层
楼主
两个单片机通过串口相互通信,一个单片机不停向另一个单片机传送数据,

发送数据的单片机:

oid Usart_Int(uint32_t BaudRatePrescaler)
{
         SCON  = 0x50;//1位起始位,8位数据位,1位停止位,异步,使能接收
         TMOD |= 0x20;//定时器1,工作方式2,8位自动重装计数值
        //例9600,28800/9600=3,TH1=253=FD;
     TH1   =256-(28800/BaudRatePrescaler);
         TL1   =256-(28800/BaudRatePrescaler);
     TCON |=0x40;//启动定时器1
         IE   |=0x90;//打开串口中断,MCU总中断
}
//发送一个字节
uint8_t send_ok=0,Receive_ok=0,TEMP_data[9]={0};
void USART_send_byte(uint8_t Tx_data)
{
        while(send_ok);//等待发送缓存为空
         SBUF = Tx_data;
        send_ok=1;//缓存标志置1
}
//发送Length-1个数据+1个数据累加和
void USART_Send(uint8_t *Buffer, uint8_t Length)
{
        uint8_t i=0;
        while(i<Length)
        {
                if(i<(Length-1))
                Buffer[Length-1]+=Buffer;
                USART_send_byte(Buffer[i++]);
        }
}
//发送一帧数据
void send_out(int16_t *Data,uint8_t length,uint8_t send)
{
        uint8_t TX_DATA[13],i=0,k=0;
        memset(TX_DATA,0,(2*length+5));//清空发送数据
        TX_DATA[i++]=0X5A;//帧头
        TX_DATA[i++]=0X5A;//帧头
        TX_DATA[i++]=send;//功能字节
        TX_DATA[i++]=2*length;//数据个数
        for(k=0;k<length;k++)//存入数据到缓存TX_DATA数组
        {
                TX_DATA[i++]=(uint16_t)Data[k]>>8;
                TX_DATA[i++]=(uint16_t)Data[k];
        }
        USART_Send(TX_DATA,(2*length+5));//发送一帧数据        
}

模块输出格式,每帧包含 10 个字节(十六进制):
①.Byte0: 0x5A 帧头标志
②.Byte1: 0x5A 帧头标志
③.Byte2: 0X45 本帧数据类型( 0x45:温度数据)
④.Byte3: 0x04 数据量(以下 4 个数据 2 组为例)
⑤.Byte4: 0x00~0xFF 数据 1 高 8 位
⑥.Byte5: 0x00~0xFF 数据 1 低 8 位
⑦.Byte6: 0x00~0xFF 数据 2 高 8 位
⑧.Byte7: 0x00~0xFF 数据 2 低 8 位
⑨.Byte8: 0x00~0xFF 校验和(前面数据 Byte0-7 累加和, 仅留低 8 位)
⑩. Byte9: 0x01~0x15 ID 号,范围 0x01~0x15 可以修改,默认是 0x14




我接收单片机是这样的写的,怎么就是收不到数据呢,大家帮我看看,
void Usart_Int(uint32_t BaudRatePrescaler)
{
         SCON  = 0x50;//1位起始位,8位数据位,1位停止位,异步,使能接收
         TMOD |= 0x20;//定时器1,工作方式2,8位自动重装计数值
        //例9600,28800/9600=3,TH1=253=FD;
     TH1   =256-(28800/BaudRatePrescaler);
         TL1   =256-(28800/BaudRatePrescaler);
     TCON |=0x40;//启动定时器1
         IE   |=0x90;//打开串口中断,MCU总中断
}

main(void)
{
        float TO=0,TA=0;
     u8 sum=0,i=0;
        int datas[2]={0};
        Usart_Int(9600);
        send_com(0x45);//发送读方位角指令
         while(1)
        {
                if(Receive_ok)//串口接收完毕
                {
                        for(sum=0,i=0;i<(TEMP_data[3]+4);i++)//TEMP_data[3]=4
                        sum+=TEMP_data;
                        if(sum==TEMP_data)//校验和判断
                        {
                                TO=(float)((TEMP_data[4]<<8)|TEMP_data[5])/100;//得到真实温度
                                TA=(float)((TEMP_data[6]<<8)|TEMP_data[7])/100;//得到真实温度
                     LED = 1;//让LED灯亮来判断数据接收完整,//小灯一真没亮过。不知道程序哪里不对,求解
                        }
                        Receive_ok=0;//处理数据完毕标志
                }
        }
}


void USART_IRQHandler(void)interrupt 4
{
        static uint8_t i=0,rebuf[9]={0};
        uint8_t sum=0;
    if(TI)//发送完成标志
        {
          TI=0;//清发送完成标志
          send_ok=0;//缓存标志置0
        }
        if(RI)//接收完成标志
        {
                rebuf[i++]=SBUF;
                RI=0;//清中断接收标志
                if (rebuf[0]!=0x5a)//帧头不对
                        i=0;        
                if ((i==2)&&(rebuf[1]!=0x5a))//帧头不对
                        i=0;
        
        if(i>3)//i等于4时,已经接收到数据量字节rebuf[3]
                {
                        if(i!=(rebuf[3]+5))//判断是否接收一帧数据完毕
                                return;        
                        switch(rebuf[2])//接收完毕后处理
                        {
                                case 0x45:
                                        if(!Receive_ok)//当数据处理完成后才接收新的数据
                                        {
                                                memcpy(TEMP_data,rebuf,9);//拷贝接收到的数据
                                                Receive_ok=1;//接收完成标志
                                        }
                                        break;
                                case 0x15:break;
                                case 0x35:break;
                        }
                        i=0;//缓存清0
                }
        
        }


}




分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:152475 发表于 2016-12-6 10:24 | 只看该作者
你先自己试一下简单的通信,你这样就贴一大段代码也不知道硬件有没有问题,一步一步慢慢调试,代码都是调出来的
回复

使用道具 举报

板凳
ID:152524 发表于 2016-12-6 11:03 | 只看该作者
你先自己试一下简单的通信,你这样就贴一大段代码也不知道硬件有没有问题,一步一步慢慢调试,代码都是调出来的
回复

使用道具 举报

地板
ID:111634 发表于 2016-12-6 11:21 | 只看该作者
本帖最后由 zl2168 于 2016-12-6 11:29 编辑

实例77  双机串行通信方式1


已知甲乙机以串行方式1进行数据传送,fOSC=11.0592MHz,波特率为1200b/sSMOD=0。甲机发送16个数据(设为16进制数09AF的共阳字段码),间隔1秒,发送后,输出到P1口显示;乙机接收后输出到P2口显示。

Proteus仿真一下,确认有效。
实例77 双机通信方式1.rar (40.4 KB, 下载次数: 29)

以上摘自张志良编著80C51单片机仿真设计实例教程——基于Keil CProteus》清华大学出版社ISBN 978-7-302-41682-1内有常用的单片机应用100案例,用于仿真实验操作,电路与程序真实可靠可信可行书中电路和程序设计有详细说明,程序语句条条有注解。

回复

使用道具 举报

5#
ID:111634 发表于 2016-12-6 11:25 | 只看该作者
本帖最后由 zl2168 于 2016-12-6 11:27 编辑

实例78  双机串行通信方式2


已知甲乙机以串行方式2进行数据传送,fOSC=12MHzSMOD=0TB8/RB8作为奇偶校验位。甲机每发送一帧数据(设为09共阳字段码,存在外ROM中),同时在P1口显示;用P2.7(驱动LED灯)显示奇偶校验位(10暗);接到乙机回复信号后,显示暗0.5秒(作为帧间隔);然后发送下一数据,直至10个数据串送完毕;显示再暗0.5秒(作为周期间隔),然后重新开始第二轮重复循环操作。乙机接收甲机发送的一帧数据后,送P2口显示;用P1.1显示第9位数据(10暗),用P1.0显示接收数据的奇偶性(奇亮偶暗);并进行奇偶校验,向甲机发送回复信号(00H表示校验正确,FFH表示出错)。若正确,甲机继续串行发送(共10帧);若出错,甲机再重发一遍,直至乙机发回正确回复信号。
Proteus仿真一下,确认有效。
实例78 双机通信方式2.rar (46.57 KB, 下载次数: 19)

以上摘自张志良编著80C51单片机仿真设计实例教程——基于Keil CProteus》清华大学出版社ISBN 978-7-302-41682-1内有常用的单片机应用100案例,用于仿真实验操作,电路与程序真实可靠可信可行书中电路和程序设计有详细说明,程序语句条条有注解。
回复

使用道具 举报

6#
ID:111634 发表于 2016-12-6 11:29 | 只看该作者
本帖最后由 zl2168 于 2016-12-6 11:36 编辑

实例79  双机串行通信方式3
Proteus仿真一下,确认有效。
实例79 双机通信方式3.rar (45.3 KB, 下载次数: 16)

以上摘自张志良编著80C51单片机仿真设计实例教程——基于Keil CProteus》清华大学出版社ISBN 978-7-302-41682-1内有常用的单片机应用100案例,用于仿真实验操作,电路与程序真实可靠可信可行书中电路和程序设计有详细说明,程序语句条条有注解。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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