xielong4183 发表于 2011-10-28 15:57:12

STC单片机串口2中断引起程序复位问题

单片机型号STC12C5A16S2,使用串口2通信时一接送数据程序就复位了,希望高手指点。
下面是代码
#include"stc_new_8051.h"
#include"intrins.h"
#include"uart.h"
#include"delay.h"
#include"jhd_12864.h"

#define SYSCLK 50000                        //定时50ms,12MHz一个时钟周期为1us,50ms=50000*1us
#define __MAX_LEN_ 6    // 数据最大长度   
/* 以下为程序协议中使用的握手信号 */   
#define __RDY_ 0x06    // 主机开始通信时发送的呼叫信号   
#define __BUSY_ 0x15    // 从机忙应答   
#define __OK_ 0x00    // 从机准备好   
#define __SUCC_ 0x0f    // 数据传送成功   
#define __ERR_ 0xf0    // 数据传送错误

#define PlaceIncatorLight P2                                        //翻身位置指示灯配置于P2口
#define MassageAndTimeIncatorLight P1                        //按摩和定时指示灯配置于P1口
#define Flash_time 8//50ms*X显示刷新时间
#define LCD_time 600//背光关闭时间50ms*X

sbit LCD_CON = P0^5;//P0.5 -->        LCD_CON 背光控制
bit BitBusy = 0;
bit BitLCDtimer = 0;//背光计时标志

unsigned char ReceiverData;
unsigned char buf;
unsigned char str;
unsigned char Timer_clock = 0;//定时器时钟变量
unsigned int Timer_LCD = 0;//背光计时时钟
unsigned char shuzu_three =
{0xff,0xf7,0xef,0xdf,0xbf,0xfe,0xfd,0xfb,0x7f,0xbe,0xdd,0xeb,0x00};//侧翻功能指示灯和CPR指示灯
//0全灭//1水平//2左侧30%//3左侧50%//4左侧100%//5右侧100%//6右侧50%//7右侧30%//8CPR//9左右100%//10左右50%//11左右30%//12全亮
unsigned char shuzu_four =
{      //0    1    2   3   4
        /*0*/0xff,0xfe,0xfd,0xfb,0xf7,
        /*1*/0xef,0xee,0xed,0xeb,0xe7,
        /*2*/0xdf,0xde,0xdd,0xdb,0xd7,
        /*3*/0xbf,0xbe,0xbd,0xbb,0xb7,
        /*4*/0x7f,0x7e,0x7d,0x7b,0x77
};//按摩指示灯和定时指示灯


/*******************************************************************************************************
** 函数名称: void Init_IO(void)
** 功能描述: I/O口初始化
** 入口参数: 无
** 出口参数: 无
********************************************************************************************************/
void init_io(void)
{
        P0M1=0xc0;          //P0.0->CS推挽,P0.1->RES推挽,P0.2->A0推挽,P0.3->SCL准双向,P0.4->SDA准双向,P0.5->LCD_CON推挽
        P0M0=0x27;                //其他为高阻

        P1M1=0x00;       
        P1M0=0xff;                //P1.0~P1.7设为推挽

        P2M1=0x00;       
        P2M0=0xff;                //P2.0~P2.7设为推挽
       
        P3M1=0xff;                //P3口全部设为高阻
        P3M0=0x00;                                                                                                                                          

        P4M1=0xc3;           //P4.2和P4.3设为双向I/O,P4.4和P4.5设为推挽
        P4M0=0x30;

        P4SW=0x70;        //设置P4脚全部为I/O口
}
/*******************************************************************************************************
** 函数名称: void Timer_init(void)
** 功能描述: 定时器初始化
** 入口参数: 无
** 出口参数: 无
********************************************************************************************************/
/*void Timer_init(void)
{
        //中断
        IE = 0x02;//开总中断,开定时器0
        //定时器
        TMOD = 0x01;//定时器0工作在方式1,16定时器,2^16=65536
        TH0 = (65536-SYSCLK)/256;//8位界点2^8=256,"/"取高8位,"%"取低8位
        TL0 = (65536-SYSCLK)%256;
        //TCON = 0x10;//启动定时器0
        TCON = 0x00;//启动定时器0
}*/

/*******************************************************************************************************
** 函数名称: void Data_p(unsigned char d_in)
** 功能描述: 数据十位和个位处理,并求得ASCII码
** 入口参数: 100以内的2位数
** 出口参数: 无
********************************************************************************************************/
void Data_p(unsigned char d_in)
{
        unsigned char sw,gw;
        sw=(d_in/10)%10;
        gw=d_in%10;
        if(sw==0)
        {
                str=' ';
        }
        else
        {
                str=sw+48;
        }
        str=gw+48;
        str='\0';//数组以空结束,便于函数strlen计算其长度
}
/*******************************************************************************************************
** 函数名称: void LCD_dis_p(void)
** 功能描述: LCD显示处理
** 入口参数: 无
** 出口参数: 无
********************************************************************************************************/
/*void LCD_dis_p(void)
{
        /*Data_p(ReceiverData);
        Display_Font(0,0,&str);
        Data_p(array_1);
        Display_Font(2,0,&str);
        Data_p(array_3);
        Display_Font(2,48,&str);
        Data_p(array_4);
        Display_Font(6,0,&str);
        Data_p(array_5);
        Display_Font(6,48,&str);*/
        //Display_Font(2,0,"Set   Left Right");
        /*Data_p(array_1*5);
        Display_Font(4,0,&str);
        Data_p(Leftairp_v);
        Display_Font(4,56,&str);
        Data_p(Rightairp_v);
        Display_Font(4,112,&str); */
        //Display_Font(6,0,"mmHgmmHgmmHg");
//}

/*******************************************************************************************************
** 函数名称:
** 功能描述:
** 入口参数: 无
** 出口参数: 无
********************************************************************************************************/
void P2P_s(unsigned char *buf)
{
        unsigned char i,ecc,len;
        ReceiverData=0xff;
        while(ReceiverData!=__RDY_)
        {
                while(!(S2CON & 0x01));
                S2CON = S2CON & 0xfe;
                ReceiverData = S2BUF;
        }
        if(BitBusy)//判断系统是否忙
        {
                send_UART_two(__BUSY_);//是,则发送忙信号
        }
        else
        {
                send_UART_two(__OK_);//否则,发送可以接收数据信号
                while(!(S2CON & 0x01));//等待中断
                S2CON = S2CON & 0xfe;//清除接收中断标志
                len = S2BUF;//读取数据长度
                ecc = len;
                ReceiverData = 0xff;
                while(ReceiverData!=__SUCC_)//如果接收不成功则继续接收
                {
                        for(i=0;i<len;i++)//接收数据
                        {
                                while(!(S2CON & 0x01));
                                S2CON = S2CON &0xfe;
                                *buf = S2BUF;
                                ecc = ecc^(*buf);//求校验
                                buf++;
                        }
                        buf-=len;//返回buf的首地址,便于下次接收数据
                        while(!(S2CON & 0x01));
                        S2CON = S2CON & 0xfe;
                        ReceiverData= S2BUF;
                        ecc = ReceiverData^ecc;
                        if(ecc!=0)
                        {
                                ReceiverData = 0xff;
                                send_UART_two(__ERR_);//校验错误,发送错误信号
                        }
                        else
                        {
                                ReceiverData = __SUCC_;
                                send_UART_two(__SUCC_);//校验正常,发送成功信号,以结束本次数据传输
                        }
                }
        }
}
/*******************************************************************************************************
** 函数名称: void timer0_init(void) interrupt 1
** 功能描述: 定时器0中断处理函数
** 入口参数: 无
** 出口参数: 无
********************************************************************************************************/
/*void timer0_init(void) interrupt 1
{
        TH0 = (65536-SYSCLK)/256;//8位界点2^8=256,"/"取高8位,"%"取低8位
        TL0 = (65536-SYSCLK)%256;
        Timer_clock++;
        if(BitLCDtimer)
        {
                Timer_LCD++;
                if(Timer_LCD>LCD_time)
                {
                        BitLCDtimer = 0;
                        LCD_CON = 1;
                }
        }
}*/

/*******************************************************************************************************
** 函数名称: void main(void)
** 功能描述: 主函数
** 入口参数: 无
** 出口参数: 无
********************************************************************************************************/
void main(void)
{
        init_io();
        delay_us(100);
        //Timer_init();
        //delay_us(100);
        //JHD_12864_init();//LCD初始化
        //delay_us(100);
        serial_port_two_initial();
        delay_us(100);
        LCD_CON=0;//开背光
        BitLCDtimer = 1;//标志置1
        //Display_Picture(3,8,4,7);//载入飞漫logo图片
        PlaceIncatorLight = shuzu_three;//翻身灯全亮
        MassageAndTimeIncatorLight = 0x00;//按摩和定时灯全亮
        delay_ms(500);//延时500ms
        //Display_Clear();//清楚屏幕,以更新显示
        BitBusy=1;//当显示时处于忙状态
        PlaceIncatorLight = shuzu_three;//翻身和CPR灯
        MassageAndTimeIncatorLight = shuzu_four;//按摩和定时灯
        //LCD_dis_p();//LCD显示处理
        //LCD_CON = 1;
        BitBusy=0;//显示结束位空闲状态
        EA = 1;//开总中断
        while(1)
        {       
                P2P_s(&buf);
                if(buf)
                {
                        LCD_CON = 0;
                        Timer_LCD = 0;
                        BitLCDtimer = 1;
                }
                BitBusy=1;//当显示时处于忙状态
                PlaceIncatorLight = shuzu_three];//翻身和CPR灯
                MassageAndTimeIncatorLight = shuzu_four]];//按摩和定时灯
                BitBusy=0;//显示结束位空闲状态
        }
}

这个程序编译后data=65.2   xdata = 0   code = 670   此时程序能正常收发
当把数组直接用code定义后其长度为806就会出错了,但是该型号的单片机有16K存储空间。望高手指点指点,谢谢!

wwwjjjwww 发表于 2011-10-28 16:15:23

看端口初始化是否为推挽输出。可以用镊子短接txd和rxd到低,stc的端口设置几个系列是反的。

xielong4183 发表于 2011-10-28 16:33:35

端口我设置为准双向的,这个有什么讲究吗?

ziluobu 发表于 2011-10-28 17:03:12

我也在用STC双串口的芯片,我发现不能同时在一个串口中断里调用另一个串口,会出问题。
我是在第一个串口里把要发的东西写到缓存里,然后等中断返回后,在主程序里调用串口2再发,这样才没问题。

xielong4183 发表于 2011-10-28 17:13:18

我只用了一个串口,是用的串口2,很奇怪的问题,我的主机程序能正常工作,从机带LCD的就不能正常工作。

dboyzju 发表于 2013-7-14 21:19:06

xielong4183 发表于 2011-10-28 17:13 static/image/common/back.gif
我只用了一个串口,是用的串口2,很奇怪的问题,我的主机程序能正常工作,从机带LCD的就不能正常工作。 ...

考虑下功耗的问题,是否同时开启引起电压下降造成了低电压复位。
页: [1]
查看完整版本: STC单片机串口2中断引起程序复位问题