xinshui 发表于 2014-11-12 15:02:21

使用STC15遇到外部中断问题

使用STC15遇到外部中断问题, 我同时使用外部中断1,UART串口1, 硬件SPI。 出现了只有主循环内有UART发送函数时,外部中断才能进入。 如果没有放置UART发送函数。 刚不能进入外部中断1.

---------------------------------------------------------------------------------------------------------

/*---------------------------------------------------------------------*/
/* --- STC MCU Limited ------------------------------------------------*/
/* --- STC15F4K60S4 系列 定时器1用作串口1的波特率发生器举例------------*/
/* --- Mobile: (86)13922805190 ----------------------------------------*/
/* --- Fax: 86-755-82905966 -------------------------------------------*/
/* --- Tel: 86-755-82948412 -------------------------------------------*/
/* --- Web: www.STCMCU.com --------------------------------------------*/
/* 如果要在程序中使用此代码,请在程序中注明使用了宏晶科技的资料及程序   */
/* 如果要在文章中应用此代码,请在文章中注明使用了宏晶科技的资料及程序   */
/*---------------------------------------------------------------------*/

//本示例在Keil开发环境下请选择Intel的8058芯片型号进行编译
//假定测试芯片的工作频率为18.432MHz

//#include "reg52.H"
#include "STC15F2K60S2.H"
#include "intrins.h"

#include "UART.h"
#include "MyType.h"
#include "config.h"


//sfr AUXR= 0x8e;               // 辅助寄存器
//sfr P_SW1 = 0xA2;                     // 外设功能切换寄存器1
//sbit P22         = P2^2;

bit busy;


void uartInit(void)
{
      EA = 0;
      
      ACC = P_SW1;
      ACC &= ~(S1_S0 | S1_S1);    //S1_S0=0 S1_S1=0
      P_SW1 = ACC;                //(P3.0/RxD, P3.1/TxD)
   
//ACC = P_SW1;
//ACC &= ~(S1_S0 | S1_S1);    //S1_S0=1 S1_S1=0
//ACC |= S1_S0;               //(P3.6/RxD_2, P3.7/TxD_2)
//P_SW1 = ACC;
//
//ACC = P_SW1;
//ACC &= ~(S1_S0 | S1_S1);    //S1_S0=0 S1_S1=1
//ACC |= S1_S1;               //(P1.6/RxD_3, P1.7/TxD_3)
//P_SW1 = ACC;

#if (PARITYBIT == NONE_PARITY)
    SCON = 0x50;                //8位可变波特率
#elif (PARITYBIT == ODD_PARITY) || (PARITYBIT == EVEN_PARITY) || (PARITYBIT == MARK_PARITY)
    SCON = 0xda;                //9位可变波特率,校验位初始为1
#elif (PARITYBIT == SPACE_PARITY)
    SCON = 0xd2;                //9位可变波特率,校验位初始为0
#endif

      //PT1 = 0;                                                                                                                // 定时器0优先级为最低。
      AUXR = 0x40;                                                // 定时器1为1T模式
      TMOD = 0x00;                                                // 定时器1为模式0(16位自动重载)
      TL1 = (65536 - (FOSC/4/BAUD));                   // 设置波特率重装值
      TH1 = (65536 - (FOSC/4/BAUD))>>8;
      TR1 = 1;                                                         // 定时器1开始启动
      ES = 1;                                                   // 使能串口中断
      EA = 1;

      //uartSendString("STC15F2K60S2 \r\n Uart Test !\r\n");
}

/*----------------------------
UART 中断服务程序
-----------------------------*/
void Uart() interrupt 4 using 2
{
      if (RI)
      {
                RI = 0;               // 清除RI位
                //P0 = SBUF;            // P0显示串口数据
                //P22 = RB8;            // P2.2显示校验位
      }
      if (TI)
      {
                TI = 0;               // 清除TI位
                busy = 0;               // 清忙标志
      }
}

/*----------------------------
发送串口数据
----------------------------*/
void uartSendData(BYTE dat)
{
    while (busy);               //等待前面的数据发送完成
    ACC = dat;                  //获取校验位P (PSW.0)
    if (P)                      //根据P来设置校验位
    {
#if (PARITYBIT == ODD_PARITY)
      TB8 = 0;                //设置校验位为0
#elif (PARITYBIT == EVEN_PARITY)
      TB8 = 1;                //设置校验位为1
#endif
    }
    else
    {
#if (PARITYBIT == ODD_PARITY)
      TB8 = 1;                //设置校验位为1
#elif (PARITYBIT == EVEN_PARITY)
      TB8 = 0;                //设置校验位为0
#endif
    }
    busy = 1;
    SBUF = ACC;               //写数据到UART数据寄存器
}

/*----------------------------
函数名称: uartSendString(char *s)
函数功能: 发送字符串。
发送较多字符时,会出现丢失现像。可能是指针丢失。

----------------------------*/
void uartSendString(char *s)
{      
      while (*s)                  //检测字符串结束标志
      {
                uartSendData(*s++);         //发送当前字符
      }
}
---------------------------------------------------------------------------------------------------

xinshui 发表于 2014-11-12 15:03:33

/*---------------------------------------------------------------------*/
/* --- STC MCU Limited ------------------------------------------------*/
/* --- STC15F4K60S4 系列 INT1中断举例----------------------------------*/
/* --- Mobile: (86)13922805190 ----------------------------------------*/
/* --- Fax: 86-755-82905966 -------------------------------------------*/
/* --- Tel: 86-755-82948412 -------------------------------------------*/
/* --- Web: www.STCMCU.com --------------------------------------------*/
/* 如果要在程序中使用此代码,请在程序中注明使用了宏晶科技的资料及程序   */
/* 如果要在文章中应用此代码,请在文章中注明使用了宏晶科技的资料及程序   */
/*---------------------------------------------------------------------*/

//本示例在Keil开发环境下请选择Intel的8058芯片型号进行编译
//假定测试芯片的工作频率为18.432MHz

#include "timer.h"

#defineNoChangedTime 9

#define DEBUG_TIMER

//sbit INT1 = P3^3;

extern unsigned char TIM;
extern unsigned char CAN_Flag;

extern void uartSendString(uint8 * pd);                                        //

/*******************************************************************************
* 函数名: Exint1_Init
* 描述    : 外部中断1初始化函数
* 输入    : 无
* 输出    : 无
* 返回值: 无
* 说明    : 无
*******************************************************************************/
void Exint1_Init(void)
{
        EA = 0;                                 // 暂时关闭中断。
        P33 = 1;
//PX1 = 1;                                // 设置外部中断1的中断优先级为高优先级
IT1 = 1;                               // 设置INT1的中断类型 (1:仅下降沿 0:上升沿和下降沿)
EX1 = 1;                               // 使能INT1中断
EA = 1;                                // 使能总中断       
}

/*******************************************************************************
* 函数名: Exint1_ISR
* 描述    : 外部中断1中断服务函数
* 输入    : 无
* 输出    : 无
* 返回值: 无
* 说明    : 用于检测MCP2515中断引脚的中断信号
*******************************************************************************/
void Exint1_ISR(void) interrupt 2 using 1
{
        CAN_Flag = 1;                                       
}

xinshui 发表于 2014-11-12 15:04:15

本帖最后由 xinshui 于 2014-11-12 15:39 编辑

void main(void)
{
      uint8 len, i = 1, j = 0;

      // UART初始化。
      uartInit();
                uartSendString(" UART init end。\r\n \r\n");      
      
      // SPI初始化,关闭所有片选。InitSpi()
      InitSpi();
                uartSendString(" SPI init end。\r\n \r\n")

      // 外部中断 1 初始化。
      Exint1_Init();
      while(1)
      {

                        if(CAN_Flag)
                        {
                           uartSendString("into Interrupt. \r\n");        // 2 不然无法进入中断               
                        }
                        else
                        {
                                uartSendString("into Interrupt. \r\n");//1 主循环必须有UART发送函数。
                        }
                }
      }

xinshui 发表于 2014-11-12 15:29:07

我查看STC15F2K32S 芯片的最下行的最后一个字母是C,应该不是A版的问题。

weare 发表于 2014-11-12 16:41:31

楼主下面这段函数怎么能看有没有进中断呢?在中断函数中打个log看看,才能知道到底有没有进外部中断吧!
while(1)
      {

                        if(CAN_Flag)
                        {
                           uartSendString("into Interrupt. \r\n");      // 2 不然无法进入中断               
                        }
                        else
                        {
                              uartSendString("into Interrupt. \r\n");//1 主循环必须有UART发送函数。
                        }
                }

xinshui 发表于 2014-11-12 18:05:25

weare 发表于 2014-11-12 16:41
楼主下面这段函数怎么能看有没有进中断呢?在中断函数中打个log看看,才能知道到底有没有进外部中断吧!
w ...

哦不好意, 代码我简化了一下。缺少些代码。
CAN_Flag = 0// 在别的文件里是默认为零。在中断里设为1.

       while(1)
      {

                        if(CAN_Flag)
                        {
                           uartSendString("into Interrupt. \r\n");      // 2 不然无法进入中断      
                          CAN_Flag = 0;                                                 // 这里补上恢复      
                        }
                        else
                        {
                              uartSendString("into Interrupt. \r\n");//1 主循环必须有UART发送函数。
                               
                        }
                }
      }

xiaobendan 发表于 2014-11-12 18:18:13

基本上不使用外部中断的

xinshui 发表于 2014-11-12 18:35:32

xiaobendan 发表于 2014-11-12 18:18
基本上不使用外部中断的

驱动 mcp2515要用的啊{:mad:}

weare 发表于 2014-11-12 19:11:17

xinshui 发表于 2014-11-12 18:05
哦不好意, 代码我简化了一下。缺少些代码。
CAN_Flag = 0// 在别的文件里是默认为零。在中断里设为1....

你if和else里面串口打出来的都是同一串东西,怎么能判断到底是有木有进中断呀?你把if和else里面的串口打印函数注释掉,然后拷贝一句到你中断函数中看看会不会打印出来!

xinshui 发表于 2014-11-12 19:49:54

weare 发表于 2014-11-12 19:11
你if和else里面串口打出来的都是同一串东西,怎么能判断到底是有木有进中断呀?你把if和else里面的串口打 ...

不好意思,那个代码改错了, 正确的如下。
                if(CAN_Flag == 0xAA)                        // || ((P3 & 0x04) == 0) )               
                {                       
                                uartSendString("\r\n\r\nReceive data.\r\n\r\n");
                        CAN_Flag = 0x00;                                                                                                                                                                                        // CAN接收到数据标志       
                }                                       
                else if( CAN_Flag == 0x00 )
                {
                        CAN_Send_Buffer(CAN_T_Buffer, 8);                                                                                                                        // CAN发送指定长度的数据
                        //uartSendString("Send data.\r\n");
                        //CAN_Send_Buffer(CAN_T_Buffer, len);                                                                                                        // CAN发送指定长度的数据
                }
通过在中断函数里设置一个IO来控制LED,证明中断能进入。
现在的问题是,中断内设置CAN_Flag在主函数内不起作用。或者中断内的变量赋值能问题? 总之,中断能进入, 但是不能改变主函数内的变量值, 或者影响到不能运行主函数!?

weare 发表于 2014-11-12 20:01:51

xinshui 发表于 2014-11-12 19:49
不好意思,那个代码改错了, 正确的如下。
                if(CAN_Flag == 0xAA)                        // || ((P3 & 0x04) == 0) )               
                {       ...

extern unsigned char CAN_Flag;这个地方CAN_Flag有在别的地方定义过了吗?没有的话为啥用extern?

xinshui 发表于 2014-11-12 20:22:18

{:sweat:} 是我代码没弄好,MCP2515代码部分没清理干净。造的干扰。中断没问题,使用也正常, 谢谢楼上各位的回贴,非常感谢。{:handshake:}
页: [1]
查看完整版本: 使用STC15遇到外部中断问题