打印

PIC串口问题

[复制链接]
5853|26
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
庄庄|  楼主 | 2011-4-19 11:33 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 庄庄 于 2011-4-20 11:21 编辑

我在用PIC单片机18系列双串口,第一个串口调通了,主动发送,中断接收。
第二个串口发送没有问题,接收不进入中断。
datasheet显示两个串口设置都一样。
哪位用过双串口,第二个串口与第一个串口有什么区别吗? 谢谢


2011年4月20日 ,问题解决。答案在18楼,谢谢大家。
沙发
yewuyi| | 2011-4-19 13:42 | 只看该作者
贴中断函数代码

使用特权

评论回复
板凳
yewuyi| | 2011-4-19 13:42 | 只看该作者
贴中断函数代码

使用特权

评论回复
地板
251566208| | 2011-4-19 13:55 | 只看该作者
同上

使用特权

评论回复
5
庄庄|  楼主 | 2011-4-19 14:47 | 只看该作者
/******************************************************************************/
/*                                                   串口中断函数  2                                                              */
/******************************************************************************/
void interrupt low_priority Usart2(void)
{
unsigned char index_comm,buf_comm;
unsigned char rx_buf;
if(RC2IF==1)                //串口2中断处理
{
        rx_buf=RCREG2;       
        if(rx_buf == 0x3A)  //界定符
           {
      com_data_num =0;
      start_receive_data_flag = 1;
           }
          if(start_receive_data_flag==1)      //开始接收界定符、地址、数据及结束符。
           {
      ser_buf[com_data_num] = rx_buf;
      com_data_num++;
      if(rx_buf == 0x0A)                  //0x0d 回车 为结束符
       {
          start_receive_data_flag = 0;
          ser_process_data_flag = 1;
       }
           }
          if(ser_process_data_flag==1)
           {
                 rx_buf=(ser_buf[5]-0x30)*10+ ser_buf[6]-0x30+6;//提取数据长度
                 buf_comm=0;
                 for(index_comm=1;index_comm<=rx_buf;index_comm++)//计算校验和
                         buf_comm=buf_comm+ser_buf[index_comm];
                 
                 //if(buf_comm==((ASCII(ser_buf[rx_buf+1]))*16+ASCII(ser_buf[rx_buf+2])))//比较校验和
                 {                       
                       //ser_com();                      //串口命令处理程序  
                        Usart_Tm2(ser_buf,com_data_num);           
                 }
                ser_process_data_flag = 0;      
           }
       
}//end if(RC2IF==1)
       
}

使用特权

评论回复
6
庄庄|  楼主 | 2011-4-19 14:50 | 只看该作者
串口 1 也是 用的这个,这是设为低优先级时的
高优先级,我也试过,也不行
同样的接收函数,串口1能进入if(RC1IF==1)    ,串口2不能,好像就没有产生中断

使用特权

评论回复
7
庄庄|  楼主 | 2011-4-19 14:52 | 只看该作者
我认为 和中断函数没关系,应该是设值不对

使用特权

评论回复
8
庄庄|  楼主 | 2011-4-19 14:53 | 只看该作者
//以下是中断定义******************************************************************************       
        GIE=0;        //中断: 1允许所有高优先级中断  0禁止所有中断
        PEIE=0;        //中断: 1允许所有低优先级中断  0禁止所有中断
        //初始化前,应禁止中断,以下中断初始化
        PIR1=0;        //中断标志清零
        IPEN=1;        //中断优先级设置:1允许优先级  0禁止优先级
       
        TMR0IP=1;//TMR0 溢出中断优先级位: 1高优先级  0低优先级
        IPR1=0x20;//串口1 优先级
        IPR2=0;
        IPR3=0x00;//串口2 优先级
        IPR4=0;IPR5=0;IPR6=0;//其它低优先级

        TMR0IE=1;//TMR0 溢出中断允许位: 1允许  0禁止
        PIE1=0x20;//允许串口1中断,允许AD中断
        PIE2=0;
        PIE3=0x20;//允许串口2中断
        PIE4=0;PIE5=0;PIE6=0;

使用特权

评论回复
9
庄庄|  楼主 | 2011-4-19 14:54 | 只看该作者
/******************************************************************************/
/*                                                   初始化函数 串口1                                                          */
/******************************************************************************/
void Usart_init1(void)
{
ABDEN=0;                //关闭自动波特率检测
BRG16=1;                //选择波特率生成器为16方式
BRGH=1;                //选择高速波特率方式
SYNC=0;                //选择异步方式

SPBRGH1=0;
SPBRG=0x33; //设置波特率为9600BPS,9600=2M/4(0x33+1)

SPEN=1;      //使能串口发送,选择高速波特率
TXEN=1;
RCSTA1=0x90; //使能串口工作,连续接收

}
/******************************************************************************/
/*                                                   初始化函数 串口2                                                          */
/******************************************************************************/
void Usart_init2(void)
{
ABDEN2=0;        //关闭自动波特率检测
BRG162=1;        //选择波特率生成器为16方式
BRGH2=1;                //选择高速波特率方式
SYNC2=0;                //选择异步方式

SPBRG2H=0;
SPBRG2=0x33; //设置波特率为9600BPS,9600=2M/4(0x33+1)

SPEN2=1;      //使能串口发送,选择高速波特率
TXEN2=1;
RCSTA2=0x90; //使能串口工作,连续接收

}

使用特权

评论回复
10
庄庄|  楼主 | 2011-4-19 15:03 | 只看该作者
/******************************************************************************/
/*                                                   串口中断函数 1                                                               */
/******************************************************************************/
void interrupt Usart(void)
{
unsigned char index_comm,buf_comm;
unsigned char rx_buf;
if(TMR0IF==1)                //定时器0中断处理
{
        TMR0IF=0;
        TMR0L=0;
        TMR0H=0xF0;       
        set_time++;
        if(set_time>=500)set_time_over=1;
}//end if(TMR0IF==1)

if(RC1IF==1)                //串口1中断处理
  {
        rx_buf=RCREG1;       
        if(rx_buf == 0x3A)  //界定符
           {
      com_data_num =0;
      start_receive_data_flag = 1;
           }
          if(start_receive_data_flag==1)      //开始接收界定符、地址、数据及结束符。
           {
      ser_buf[com_data_num] = rx_buf;
      com_data_num++;
      if(rx_buf == 0x0A)                 //0x0d 回车 为结束符
       {
          start_receive_data_flag = 0;
          ser_process_data_flag = 1;
       }
           }
          if(ser_process_data_flag==1)
           {
                 rx_buf=(ser_buf[5]-0x30)*10+ ser_buf[6]-0x30+6;//提取数据长度
                 buf_comm=0;
                 for(index_comm=1;index_comm<=rx_buf;index_comm++)//计算校验和
                         buf_comm=buf_comm+ser_buf[index_comm];
                 
                 //if(buf_comm==((ASCII(ser_buf[rx_buf+1]))*16+ASCII(ser_buf[rx_buf+2])))//比较校验和
                 {                       
                       //ser_com();                      //串口命令处理程序  
                        Usart_Tm(ser_buf,com_data_num);           
                 }
                ser_process_data_flag = 0;      
           }
  }//end if(RC1IF==1)
       
}

使用特权

评论回复
11
yewuyi| | 2011-4-19 15:09 | 只看该作者
根据俺了解,你用的这个型号可以支持两级中断优先级。

而你的中断代码中之判断了中断标志位,而没有判断中断容许位,嘿嘿,好像这是不容许的,可能错误就是如此发生了。

你可忙着认为你的中断函数没有错误哦。

使用特权

评论回复
12
庄庄|  楼主 | 2011-4-19 15:19 | 只看该作者
中断允许位? 我在主函数初始化时 设置为1 了
请教, 在这里 怎么写?
谢谢

使用特权

评论回复
13
yewuyi| | 2011-4-19 15:31 | 只看该作者
例如:
if(TMR0IF&&TMR0IE){}

使用特权

评论回复
14
庄庄|  楼主 | 2011-4-19 15:52 | 只看该作者
还是不进 中断
定时器0,串口1都能进入,串口2不进入
我不明白ye工为什么要这么写,没有查到这方面资料,但我照着做了,还是不行。

使用特权

评论回复
15
yewuyi| | 2011-4-19 16:35 | 只看该作者
如果多中断源共用一个中断向量的话,所有的中断源都加上中断容许位标志一起判断。

使用特权

评论回复
16
yewuyi| | 2011-4-19 16:35 | 只看该作者
如果多中断源共用一个中断向量的话,所有的中断源都加上中断容许位标志一起判断。

使用特权

评论回复
17
庄庄|  楼主 | 2011-4-19 16:52 | 只看该作者
我认为:它不进入中断,在中断里判断什么应该不起作用,现在需要想办法让它进入中断

使用特权

评论回复
18
庄庄|  楼主 | 2011-4-19 17:05 | 只看该作者
问题解决了,还是初始化的问题,加上ANCON2=0;就好了,我原来认为默认值应该是0,实际是0xFF,刚才看资料,看到了。
谢谢大家
让大家费心了,编程序时,只看通讯部分,犯了这个错误,看资料不够全面。以下是完整代码:
//单片机引脚定义******************************************************************************
        LCDSE0=0;LCDSE1=0;LCDSE2=0;LCDSE3=0;LCDSE4=0;LCDSE5=0;LCDEN=0;//关闭液晶驱动功能
        OSCCON=0x46;//使用内部16M晶振8分频=2M
        PORTA=0;LATA=0;TRISA=0;
        PORTB=0;LATB=0;TRISB=0x0B;RBPU=0;        //按键引脚和OK指示灯定义
        PORTC=0;LATC=0;TRISC=0xC0;                        //SPI1,串口1,工作指示灯引脚定义
        PORTD=0;LATD=0;TRISD=0x20;RDPU=1;        //数码管显示,RS485控制,看门狗引脚定义
        PORTE=0;LATE=0;TRISE=0;                         //LED引脚定义
        PORTF=0;LATF=0;TRISF=0;
        PORTG=0;LATG=0;TRISG=0x04;                        //串口2引脚定义
        PORTH=0;LATH=0;TRISH=0;

        ODCON1=0;ODCON2=0;ODCON3=0;ANCON2=0;
        //以下是中断定义******************************************************************************       
        GIE=0;        //中断: 1允许所有高优先级中断  0禁止所有中断
        PEIE=0;        //中断: 1允许所有低优先级中断  0禁止所有中断
        //初始化前,应禁止中断,以下中断初始化
        PIR1=0;        //中断标志清零
        IPEN=1;        //中断优先级设置:1允许优先级  0禁止优先级
       
        TMR0IP=1;//TMR0 溢出中断优先级位: 1高优先级  0低优先级
        IPR1=0x20;//串口1 优先级
        IPR2=0;
        IPR3=0x00;//串口2 优先级
        IPR4=0;IPR5=0;IPR6=0;//其它低优先级

        TMR0IE=1;//TMR0 溢出中断允许位: 1允许  0禁止
        PIE1=0x20;//允许串口1中断,允许AD中断
        PIE2=0;
        PIE3=0x20;//允许串口2中断
        PIE4=0;PIE5=0;PIE6=0;
/******************************************************************************/
/*                                                   初始化函数 串口1                                                          */
/******************************************************************************/
void Usart_init1(void)
{
ABDEN=0;                //关闭自动波特率检测
BRG16=1;                //选择波特率生成器为16方式
BRGH=1;                //选择高速波特率方式
SYNC=0;                //选择异步方式

SPBRGH1=0;
SPBRG=0x33; //设置波特率为9600BPS,9600=2M/4(0x33+1)

SPEN=1;      //使能串口发送,选择高速波特率
TXEN=1;
RCSTA1=0x90; //使能串口工作,连续接收

}
/******************************************************************************/
/*                                                   初始化函数 串口2                                                          */
/******************************************************************************/
void Usart_init2(void)
{
ABDEN2=0;        //关闭自动波特率检测
BRG162=1;        //选择波特率生成器为16方式
BRGH2=1;                //选择高速波特率方式
SYNC2=0;                //选择异步方式

SPBRG2H=0;
SPBRG2=0x33; //设置波特率为9600BPS,9600=2M/4(0x33+1)

SPEN2=1;      //使能串口发送,选择高速波特率
TXEN2=1;
RCSTA2=0x90; //使能串口工作,连续接收

}
/*****************************************************************************/
/*                                                   ASCII转成十六进制                                               */
/*****************************************************************************/
unsigned char ASCII(unsigned char dataf)
{
unsigned char resc;
if(dataf<=0x39) resc=dataf-0x30;
else resc=dataf-0x37;
return resc;
}
/******************************************************************************/
/*                                                   发送函数 串口1                                                            */
/******************************************************************************/
void Usart_T(unsigned char dataf)
{
int index;
RS485=1;
for(index=0;index<1000;index++)//检测发送器是否为空
  {
        if(TRMT==1)break;
  }
TXREG1=dataf;                                        //把数据写入缓冲区
for(index=0;index<1000;index++)//等待发送完毕
  {
        if(TX1IF==1)break;
  }
RS485=0;
//TX1IF=0;                                                //发送中断清零
}
/****************************************************************************/
/*                                                   发送函数 num个 数据   串口1                                         */
/****************************************************************************/
void Usart_Tm(unsigned char *data,unsigned char num)
{
unsigned char i;
for(i=num;i>0;i--)
  {
     Usart_T(*data);
        data++;
  }
}
/******************************************************************************/
/*                                                   发送函数 串口2                                                            */
/******************************************************************************/
void Usart_T2(unsigned char dataf)
{
int index;
//RS485=1;
for(index=0;index<1000;index++)//检测发送器是否为空
  {
        if(TRMT2==1)break;
  }
TXREG2=dataf;                                        //把数据写入缓冲区
for(index=0;index<1000;index++)//等待发送完毕
  {
        if(TX2IF==1)break;
  }
//RS485=0;
//TX2IF=0;                                                //发送中断清零
}
/****************************************************************************/
/*                                           发送函数 num个 数据 串口2                                               */
/****************************************************************************/
void Usart_Tm2(unsigned char *data,unsigned char num)
{
unsigned char i;
for(i=num;i>0;i--)
  {
     Usart_T2(*data);
        data++;
  }
}
/******************************************************************************/
/*                                                   串口中断函数 1                                                               */
/******************************************************************************/
void interrupt Usart(void)
{
unsigned char index_comm,buf_comm;
unsigned char rx_buf;
if(TMR0IF==1)                //定时器0中断处理
{
        TMR0IF=0;
        TMR0L=0;
        TMR0H=0xF0;       
        set_time++;
        if(set_time>=500)set_time_over=1;
}//end if(TMR0IF==1)

if(RC1IF==1)                //串口1中断处理
  {
        rx_buf=RCREG1;       
        if(rx_buf == 0x3A)  //界定符
           {
      com_data_num =0;
      start_receive_data_flag = 1;
           }
          if(start_receive_data_flag==1)      //开始接收界定符、地址、数据及结束符。
           {
      ser_buf[com_data_num] = rx_buf;
      com_data_num++;
      if(rx_buf == 0x0A)                 //0x0d 回车 为结束符
       {
          start_receive_data_flag = 0;
          ser_process_data_flag = 1;
       }
           }
          if(ser_process_data_flag==1)
           {
                 rx_buf=(ser_buf[5]-0x30)*10+ ser_buf[6]-0x30+6;//提取数据长度
                 buf_comm=0;
                 for(index_comm=1;index_comm<=rx_buf;index_comm++)//计算校验和
                         buf_comm=buf_comm+ser_buf[index_comm];
                 
                 //if(buf_comm==((ASCII(ser_buf[rx_buf+1]))*16+ASCII(ser_buf[rx_buf+2])))//比较校验和
                 {                       
                       //ser_com();                      //串口命令处理程序  
                        Usart_Tm(ser_buf,com_data_num);           
                 }
                ser_process_data_flag = 0;      
           }
  }//end if(RC1IF==1)
       
}
/******************************************************************************/
/*                                                   串口中断函数  2                                                              */
/******************************************************************************/
void interrupt low_priority Usart2(void)
{
unsigned char index_comm,buf_comm;
unsigned char rx_buf;
/*
if(ADIF==1)
{
        ADIF=0;
        adc[adc_start][ad_index]=ADRESH*256+ADRESL;
        ad_index++;
        if(ad_index>=AD_BUF_NUM)
        {
                adc_start++;
                ad_index=0;
                ADIE=0;       
                ADIE=0;
                ADON=0;
                GO_nDONE=0;       
        }
}
*/
if(RC2IF==1)                //串口2中断处理
{
        rx_buf=RCREG2;       
        if(rx_buf == 0x3A)  //界定符
           {
      com_data_num =0;
      start_receive_data_flag = 1;
           }
          if(start_receive_data_flag==1)      //开始接收界定符、地址、数据及结束符。
           {
      ser_buf[com_data_num] = rx_buf;
      com_data_num++;
      if(rx_buf == 0x0A)                  //0x0d 回车 为结束符
       {
          start_receive_data_flag = 0;
          ser_process_data_flag = 1;
       }
           }
          if(ser_process_data_flag==1)
           {
                 rx_buf=(ser_buf[5]-0x30)*10+ ser_buf[6]-0x30+6;//提取数据长度
                 buf_comm=0;
                 for(index_comm=1;index_comm<=rx_buf;index_comm++)//计算校验和
                         buf_comm=buf_comm+ser_buf[index_comm];
                 
                 //if(buf_comm==((ASCII(ser_buf[rx_buf+1]))*16+ASCII(ser_buf[rx_buf+2])))//比较校验和
                 {                       
                       //ser_com();                      //串口命令处理程序  
                        Usart_Tm2(ser_buf,com_data_num);           
                 }
                ser_process_data_flag = 0;      
           }
       
}//end if(RC2IF==1)
       
}
希望这个代码对大家有用,结贴。
zhuang   2011.04.19

使用特权

评论回复
19
yewuyi| | 2011-4-19 17:10 | 只看该作者
对于PIC来说:发生中断并进入中断向量并不代表这中断函数一定会得到执行,这个就和代码有关系了。

另外,如果高优先级中断发生速度超过了一定程度,则可能始终在处理一些高优先级中断,而低优先级中断会被淹没。

可能会有很多,你没有完全弄清楚前,切勿盲目的写一堆代码,否则,写了也是白忙,写了也会再删除重写。

使用特权

评论回复
20
庄庄|  楼主 | 2011-4-19 17:25 | 只看该作者
ye工说的,我以前遇到过,麻烦不断,死机都出现了。所以有段时间不敢用中断,时隔三年,呵呵,我又有信心了。感谢ye工。

使用特权

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

本版积分规则

个人签名:本人QQ群:35882490,职业:单片机开发 工作地点:西安

33

主题

205

帖子

1

粉丝