打印

无线通讯之前一步,UART的中断问题?

[复制链接]
1770|12
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zijingzelan001|  楼主 | 2014-9-4 14:08 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
正在做一个无线通讯,外接的是APC240CF的无线通讯模块,设置P2.4输出和P2.5输入,准备在USART0的通讯基础上实现,485通讯我已经实现了,经过删减后,但是我发现我的这个程序无法进入通讯中断。其次我把whil(1)和中断标志位进入判定语句receive_flag==1:删除后,427芯片TXD脚可以保持一直发送固定的信号,但是RXD脚也受到了影响,也一致产生固定的信号,起波长与TXD的波几乎一致,只是开头和结尾为1,中间为0。当不删除的时候(即如下程序)示波器可以观察,不过这样用示波器观察在进入mian.c之后要执行WMSendRDData(ComBuf);的时候与我预计的没什么问题,毕竟度只是初始化,但是一执行WMSendRDData(ComBuf);语句请教下我这边是出现了什么问题了?附程序和头文件
主程序 main.c
#include  <msp430x42x.h>
#include  "main.h"  
uchar8 ComBuf[COMBUFLEN];
uchar8 BufNum=0;
uint32 FV=5432;       // 流速 Flow Velocity   
uint32 FL=1111;   // 流量   
int receive_flag=0;
uchar8 WMAddress[7]={1,2,3,4,5,6,7};
void InitUART0(void) //波特率初始化
{
// case 1200:
    UTCTL0 = SSEL0;       // UCLK = ACLK
    UBR00 = 0x1b;         // 32768/1200 = 27.307
    UBR10 = 0x00;                        
    UMCTL0 = 0x11;        //调整字节UMCTL0中1的个数为0.307*8=2.45≈2,均匀分布1得到0x11
}
void BasicTimer_Init (void)                                // BasicTimer On
{
    BTCTL |= BTDIV + BT_fCLK2_DIV16;            // ACLK/(256*16)
    IE2   |= BTIE;                              // Enable BT interrupt
}

void DisableWDT(void)//About WDT   关闭看门狗  
{
  WDTCTL = WDTPW + WDTHOLD;                   // Stop WDT  
}
void DCO_Init(void)//DCO初始化
{
  uint16 i;
  
  FLL_CTL0    = XCAP18PF + DCOPLUS;           // Configure MCLK
  SCFQCTL     = 60;                               
  SCFI0       = FLLD_2;                                    // SMCLK = MCLK = 32.768*(60+1)*2 = 399.77K
  SCFI1       = 0;      
  
  do {
    IFG1 &= ~OFIFG;                         // Clear oscillator fault flag
    for (i = 5000; i; i--);                // Delay
  } while(IFG1 & OFIFG);                      // Test osc fault flag  
}

//串口初始化
void Uart0_Init(void)  
{
  P2SEL|=BIT4+BIT5;
  P2DIR|=BIT4;
  P2DIR&=~BIT5;
  U0CTL |= SWRST;                //控制寄存器位
  U0CTL &= ~(SYNC + MM);
  UCTL0  |= CHAR + PEV + PENA;                // 8-bit character
  InitUART0();
  ME1    |= UTXE0 + URXE0;                    // Enable USART0 TXD/RXD
  UCTL0  &=~SWRST;                            // Initialize USART state machine

  IE1    |= URXIE0;                           // Enable USART0 RX interrupt   
  IE1   &=~ UTXIE0;              //发送中断关闭;
  IFG1   = 0X00;                 //中断标志位清零
}

//发送一个字节
void TxdOneByte(uchar8 ch)
{
  while(!(UTCTL0 & TXEPT));
  TXBUF0 = ch;
}

//发送一个缓冲帧
void TxdBuf (uchar8 buf[],uchar8 len)
{
  int i;
  for(i = 0; i < len; i++) {
    TxdOneByte(buf[i]);
  }
}
void LToOctal(unsigned char *ptr, unsigned long mun)
{
  int i=4;
  for(;i>=0;i--)
  {
    ptr[i]=mun%10;
    mun=mun/10;
  }
}
void delay(int ms)
{
  int sub=200;
  for(;ms>=0;ms--)
  sub--;
}
///////////////////////////////////////////////////////////////////////   
#pragma vector =UART0RX_VECTOR
__interrupt void USART0_RX (void)
{
delay(100);
  _DINT();
  receive_flag=1;
  ComBuf[BufNum++] = RXBUF0;
  if(BufNum == COMBUFLEN) //防止溢出
    BufNum = 0;     
    _EINT();
}
//水表接收到读操作后返回的响应数据处理
void WMSendRDData(uchar8 pdata[])        //pdata为串口接收到的数据,RtnRslt为返回的帧起始地址
{
  uchar8 rtnrslt[60];
  uchar8 i=0,check=0;
  
  for(i=0;i<4;i++)
    rtnrslt[i] = 0XFE;//COMLEADER;
  rtnrslt[i++] = 0X68;//COMHEAD;
  rtnrslt[i++] = 0X16;//COMTYPE;
  rtnrslt[i++] = WMAddress[0];
  rtnrslt[i++] = WMAddress[1];
  rtnrslt[i++] = WMAddress[2];
  rtnrslt[i++] = WMAddress[3];
  rtnrslt[i++] = WMAddress[4];
  rtnrslt[i++] = WMAddress[5];
  rtnrslt[i++] = WMAddress[6];
  rtnrslt[i++] = pdata[9]+0x80;        //返回的应答命令为原命令再加0x80
  rtnrslt[i++] = 0x16;//LENREADDATA;
  rtnrslt[i++] = pdata[11]; //DI0
  rtnrslt[i++] = pdata[12]; //DI1
  rtnrslt[i++] = 0;   //SER
      LToOctal(&rtnrslt[50],FL);   //当前累积流量,定点数,两位小数
      rtnrslt[i++] = rtnrslt[53];
      rtnrslt[i++] = rtnrslt[52];
      rtnrslt[i++] = rtnrslt[51];
      rtnrslt[i++] = rtnrslt[50];
      rtnrslt[i++] = 0x2C;          //单位  m3
      
      LToOctal(&rtnrslt[50],FV);   //瞬时流量,定点数,4位小数
      rtnrslt[i++] = rtnrslt[53];
      rtnrslt[i++] = rtnrslt[52];
      rtnrslt[i++] = rtnrslt[51];
      rtnrslt[i++] = rtnrslt[50];
      rtnrslt[i++] = 0x35;          //单位  m3/h

//      rtnrslt[i++] = Data8ToBCD(30);   //实时时间,sec
//      rtnrslt[i++] = Data8ToBCD(WorkTime.min/480);   //实时时间,min
//      rtnrslt[i++] = Data8ToBCD(WorkTime.hour);     //实时时间,hour
//      rtnrslt[i++] = Data8ToBCD(WorkTime.day);      //实时时间,day,
//      rtnrslt[i++] = Data8ToBCD(WorkTime.month);    //实时时间,月
//      rtnrslt[i++] = Data8ToBCD(WorkTime.year);     //实时时间,年低八位
//      rtnrslt[i++] = 0x20;            //实时时间,年高八位

      rtnrslt[i++] = 0;            //水表状态ST1 用户自定义
      
      rtnrslt[59] = i;
      for(i=4;i<(rtnrslt[59]);i++)//校验计算
      {
        check += rtnrslt[i];
      }
      i = rtnrslt[59];
        rtnrslt[i++] = check;
  rtnrslt[i++] = 0X16;//COMREAR;        //帧结束
  TxdBuf(rtnrslt,i);
}
void main(void)   //主程序
{
  DisableWDT();  //禁止看门狗,方便系统初始化
  DCO_Init();
  BasicTimer_Init();
  Uart0_Init();

   while(1)
  {
if (receive_flag==1)
{
  WMSendRDData(ComBuf);
  receive_flag=0;
}
  Delay_ZZG(200);
  }

}


void Delay_ZZG(unsigned int ms)   
{                              
unsigned int i,j;
for( i=0;i<ms;i++)
for(j=0;j<2000;j++);        //8MHz晶振时
}








//将无符号8位数据转换成压缩BCD码
uchar8 Data8ToBCD(uchar8 dat)
{
  uchar8 bcd=0;
  
  if(dat > 99)
    return 0;
  
  while(dat > 9)
  {
    dat -= 10;
    bcd++;
  }
  bcd <<= 4;
  bcd += dat;
   
  return bcd;  
}

const uchar8 BCD_DA_Table[10]={0,6,12,18,24,30,36,42,48,54};//BCD码的十进制调整DA的参数表

//将压缩BCD码转换成无符号8位数
uchar8 BCDToData8(uchar8 bcd)
{
  return(bcd - BCD_DA_Table[bcd>>4]);
}
头文件main.h
#ifndef _MAIN_H_
#define _MAIN_H_
//#include  <string.h>

//////////////////////////////////////////////////////
typedef unsigned char uchar8;
typedef unsigned int uint16;           
typedef unsigned long uint32;
typedef unsigned long long uint64;

#define COMBUFLEN 120
#define ComSendBuf (ComBuf+80)    //接收缓冲大小,后40字节并共用于半双工通信时的发送
//#define  COMREAR 16
//#define  COMLEADER 16

//函数外部声明
extern unsigned char ComBuf[COMBUFLEN];

extern void Uart0_Init (void);
extern void TxdOneByte(uchar8 ch);
extern void TxdBuf (unsigned char buf[],unsigned char len);


//extern unsigned char WMRcvDataProcess(unsigned char pdata[], unsigned char rtnrslt[]);//水表接收到的串口帧数据预处理,进行帧判断和错误处理
extern void WMSendRDData(unsigned char pdata[]);        //水表接收到读操作后返回的响应数据处理//pdata为串口接收到的数据,RtnRslt为返回的帧起始地址

extern void InitUART0(void);
extern void  LToOctal(unsigned char *ptr, unsigned long mun);// rljasm.s43

extern unsigned char Data8ToBCD(unsigned char dat);// rljasm.s43 //将数据转换成压缩BCD码
extern unsigned char BCDToData8(unsigned char bcd);//将压缩BCD码转换成无符号8位数

extern void BasicTimer_Init (void);  

extern  void Delay_ZZG(unsigned int ms);


#endif

相关帖子

沙发
dirtwillfly| | 2014-9-4 21:39 | 只看该作者
没看出问题出在哪里。
不过有个小bug要注意。
在串口中断中,最后重新使能了中断。
但在主函数中while(1)内代码有可能被中断在任意位置给打断并改写ComBuf

使用特权

评论回复
板凳
i1mcu| | 2014-9-4 23:59 | 只看该作者
怎么个问题?

使用特权

评论回复
地板
i1mcu| | 2014-9-5 00:00 | 只看该作者
看看延时函数有问题么

使用特权

评论回复
5
i1mcu| | 2014-9-5 00:00 | 只看该作者

使用特权

评论回复
6
i1mcu| | 2014-9-5 00:01 | 只看该作者
直接在接收中断发送不久行了么

使用特权

评论回复
7
zijingzelan001|  楼主 | 2014-9-5 08:29 | 只看该作者
i1mcu 发表于 2014-9-5 00:01
直接在接收中断发送不久行了么

可是现在我进不去中断,设置查过资料了,应该没问题。一般情况下,芯片从外界接收到一个信号的时候中断标志位会自动置位,从而进入中断,可是我现在外界的信号能观察到,但是现在,我既不能进入中断,也不能把我要的信息传递出来

使用特权

评论回复
8
zijingzelan001|  楼主 | 2014-9-5 08:32 | 只看该作者
i1mcu 发表于 2014-9-5 00:00
看看延时函数有问题么

延时我用的是32768HZ的晶振,上面我套用了别人的延时,进行修改后,Delay_ZZG(200);是延时800ms的,不过这影响进入中断么,求指点

使用特权

评论回复
9
zijingzelan001|  楼主 | 2014-9-5 08:40 | 只看该作者
dirtwillfly 发表于 2014-9-4 21:39
没看出问题出在哪里。
不过有个小bug要注意。
在串口中断中,最后重新使能了中断。

不过尴尬的是目前连中断都没进去,_DINT();和_EINT();是参考论坛上的一些人提供的一些例程添加上去的,我觉得到时可有可无,现在我已经去掉了,现在我的中断程序是这样的:
#pragma vector =UART0RX_VECTOR
__interrupt void USART0_RX (void)
{
//delay(100);
//  _DINT();
  receive_flag=1;
//    _EINT();
}
主程序是这样的:
void main(void)   //主程序
{
  DisableWDT();  //禁止看门狗,方便系统初始化
  DCO_Init();
  BasicTimer_Init();
// TimerA_Init();
  Uart0_Init();
//_BIS_SR(LPM0_bits + GIE);                       //进入低功耗模式,打开总中断
   while(1)
  {
if (receive_flag==1)
{
  ComBuf[BufNum++] = RXBUF0;
  if(BufNum == COMBUFLEN) //防止溢出
    BufNum = 0;  
  WMSendRDData(ComBuf);
  receive_flag=0;
}
  Delay_ZZG(200);
  }

}
我昨天浏览了论坛,说最好不要在终端里面执行程序,比如字符串的赋值,能问下是不是这样子的啊。现在我也这么做了,只是设了一个标志位,不过依旧无法进入中断,请斑竹大人指点

使用特权

评论回复
10
dirtwillfly| | 2014-9-5 08:58 | 只看该作者
zijingzelan001 发表于 2014-9-5 08:40
不过尴尬的是目前连中断都没进去,_DINT();和_EINT();是参考论坛上的一些人提供的一些例程添加上去的,我 ...

具体到程序是全部放在中断服务程序中,还是只放一部分,需要根据具体的程序来选择。
如果代码执行时间不长的话,可以都放在中断服务程序中执行。这样可以更充分地利用msp430的低功耗特性
如果代码执行时间比较长

使用特权

评论回复
11
dirtwillfly| | 2014-9-5 09:06 | 只看该作者
如果代码执行时间比较长,建议把代码放在中断服务程序外。
但使用时也要注意临界代码的执行。临界代码的概念,网上有很多这个介绍,你可以看看

使用特权

评论回复
12
zijingzelan001|  楼主 | 2014-9-5 09:36 | 只看该作者
dirtwillfly 发表于 2014-9-5 09:06
如果代码执行时间比较长,建议把代码放在中断服务程序外。
但使用时也要注意临界代码的执行。临界代码的概 ...

临界代码指的是非常重要的代码,不允许被中断,所以执行期间要屏蔽中断。执行完后马上要开中断,否则容易引起系统错误...而且,关中断的时间不宜长,也就是说临界代码必须非常短。
这样就可以很好理解了,谢谢斑竹大人,我继续寻找不能进入中端的原因ing

使用特权

评论回复
13
zijingzelan001|  楼主 | 2014-9-9 14:32 | 只看该作者
我已经发现了问题,我再另外一个地方加了中断源的判断,所以可以结帖了

使用特权

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

本版积分规则

5

主题

78

帖子

0

粉丝