打印

PIC单片机串口通讯调试不稳定

[复制链接]
4940|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
烟雨蒙蒙|  楼主 | 2011-7-22 11:17 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 烟雨蒙蒙 于 2011-7-22 11:19 编辑

我用PIC16F877A单片机做从机,电脑做主机,两个通讯先用485不通,最后用232,发现单片机能发送正确,但接受有时候正确,有时候就不正确,而且重复性特别差。以下是我的C语言程序。大家帮忙看看那有问题。谢谢!
#include <pic.h>
__CONFIG(0x3531);
#define _asm{"nop"} NOP()
#define uchar  unsigned char
#define uint   unsigned int
uchar receive[8];  // 接收数据数组
uchar receiv[8]={1,2,3,4,5,6,7,8};
uchar receive_count=0;// 接收数据个数计数
uchar send_count=0; // 发送数据个数计数
uchar flag;      // =1,接收到8个数据
uchar a1,a2,a3,a4,a5,a6,a7,a0;
//=========================延时1MS函数=======================================
void delay(unsigned int n)
{
   unsigned int i,j;
   for(i=0;i<n;i++)
      for(j=0;j<110;j++);
}
//SCI部件初始化子程序
void   sciint()
{   
     TRISB = 0xc0;
     TRISC = 0x80;
     SPBRG=0x19;  //将传输的波特率设置为9600
     TXSTA=0x04;//B100  SYNC=0;BRGH=1 异步高速方式传输8bit数据
     RCSTA=0x80;//SPEN=1;允许同步串行口工作
     RB1=0;
     TXEN=0;
     CREN=1;        //允许接收数据
}
main ()
{
   sciint();//SCI部件初始化子程序
   RCIF=0;
   INTCON=0x00;
   while(1)
      {
        while(1)
          {
            if(RCIF==1)  break;
          }
        NOP();
        receive[receive_count]=RCREG; //接收数据并存储
        receive_count++;     // 接收计数器加
        RCIF=0;
        if(receive_count>7)     // 如果已经接收到8个数据
         {
              CREN=0;
              a0=receive[0];
     a1=receive[1];
     a2=receive[2];
     a3=receive[3];
     a4=receive[4];
     a5=receive[5];
     a6=receive[6];
     a7=receive[7];
              receive_count=0;    // 接收计数器清0
              flag=1;    //置接收到数据标志
              RB1=1;
              TXEN=1;    //使能
         }
       while(flag)
         {   
             TXREG=receive[send_count];
          send_count++;  // 发送计数器加1
             delay(10);
              while(1)
            {
             if(TXIF==1)  break;
            }
             if(send_count>7)
               {
                 TXEN=0;
                 send_count=0;
                 flag=0;
                 RB1=0;
                 CREN=1;        //允许接收数据
               }
        }
     }
}
沙发
yewuyi| | 2011-7-22 11:45 | 只看该作者
UART的操作请使用中断,否则你将无法保证收发的正确。

看到那个delay将会是一种无限折磨,请学会写一个无阻塞的任务调度程序。

使用特权

评论回复
板凳
兰天白云| | 2011-7-22 16:08 | 只看该作者
时序问题要注意,比如电脑把8个数据分几次传给你

使用特权

评论回复
地板
烟雨蒙蒙|  楼主 | 2011-7-22 16:45 | 只看该作者
3# 兰天白云
8个数可以一次性写入串口调试助手然后发送吗?

使用特权

评论回复
5
烟雨蒙蒙|  楼主 | 2011-7-22 16:48 | 只看该作者
2# yewuyi
恩,我写了一个中断的程序,但是只能第一次收发正确,我接受用的中断,发送没有用中断。这是程序:
#include <pic.h>
__CONFIG(0x3531);
unsigned char receive232[8];  // 接收数据数组
unsigned char send232[8]={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08};  // 发送数据数组
unsigned char receive_count=0;// 接收数据个数计数
unsigned char send_count=0; // 发送数据个数计数
unsigned char flag,flag1; // =1,接收到8个数据
unsigned char a0,a1,a2,a3,a4,a5,a6,a7;
//=========================延时1MS函数=======================================
void delay(unsigned int n)
{
   unsigned int i,j;
   for(i=0;i<n;i++)
      for(j=0;j<110;j++);
}
/* ****************************************************************
** 函 数 名: sciinitial()
** 功能描述: 232串行通讯初始化子程序,设置低优先级中断接收,使能232收
*************************************************************** */
void init()
{
TRISB = 0xc0;
TRISC = 0x80;
TXSTA = 0x04;    // 选择异步高速方式传输8位数据
RCSTA = 0x80;    // 允许串行口工作使能,
SPBRG = 0x19;    // 4M晶振时波特率为25
}
/* ****************************************************************
** 函 数 名: interrupt low_priority LOW_ISR()
** 功能描述: 低优先级中断子程序:RS232中断接收、中断发送
*************************************************************** */
void interrupt ISR(void)
{
  GIE=0;
  if(RCIF==1)
   {
    receive232[receive_count]=RCREG; //接收数据并存储
    receive_count++;     // 接收计数器加1
    if(receive_count>7)     // 如果已经接收到8个数据
      {
        receive_count=0;    // 接收计数器清0
        flag=1;    //置接收到数据标志
      }
   }
GIE=1;
}
void main()     
{
init();    // 串行通讯初始化子程序
TXIE = 0;  //开发送中断
RCIE = 1;  //开接收中断
PEIE = 1;  //开外设中断
GIE = 1;  //开总中断
TXEN = 0;  //发送使能
CREN = 1;  //接收使能
while(1)
{
if(flag==1) // 是否接收到通信数据
  {
   CREN=0;
   flag=0;
   a0=receive232[0];
   a1=receive232[1];
   a2=receive232[2];
   a3=receive232[3];
   a4=receive232[4];
   a5=receive232[5];
   a6=receive232[6];
   a7=receive232[7];
   flag1=1;
  }
if(flag1==1)
  {
    TXEN=1;
    TXREG=receive232[send_count];
    send_count++;  // 发送计数器加1
    delay(10);
    while(1)
   {
    if(TXIF==1)  break;
   }
   if(send_count>7)
     {
       TXEN=0;
       flag1=0;
       send_count=0;
       CREN=1;        //允许接收数据
       GIE=1;
     }
   }
}
}

使用特权

评论回复
6
兰天白云| | 2011-7-22 17:24 | 只看该作者
你可以把8个数一次性写入串口调试助手,但电脑会不会连着发,鬼知道

使用特权

评论回复
7
烟雨蒙蒙|  楼主 | 2011-7-22 17:38 | 只看该作者
6# 兰天白云
那你看我上边那个中断写的程序,我是一次性发的,可是接收和发送只有第一次正确

使用特权

评论回复
8
烟雨蒙蒙|  楼主 | 2011-7-22 17:40 | 只看该作者
7# 烟雨蒙蒙
我发现单片机发送怎么写都可以,只要发送字节间延时就行了,可是单片机接收就搞不懂了。

使用特权

评论回复
9
兰天白云| | 2011-7-23 08:19 | 只看该作者
查问题的思路很有学问

建议你只搞个接收试试,电脑只发送,看看到底怎么接收的

使用特权

评论回复
10
烟雨蒙蒙|  楼主 | 2011-7-25 08:36 | 只看该作者
9# 兰天白云
我只用接收试过,接收的数据就像我现在写的那样,还是断断续续,我就想是不是这的接收延时有什么不妥。需要加延时来缓冲。希望指点,谢谢!

使用特权

评论回复
11
XIEYUANBIN| | 2011-7-26 12:44 | 只看该作者
GIE的开关在中断中由系统自动控制,不需要你手动开关。

使用特权

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

本版积分规则

0

主题

34

帖子

1

粉丝