使用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++); //发送当前字符
}
}
--------------------------------------------------------------------------------------------------- /*---------------------------------------------------------------------*/
/* --- 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: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发送函数。
}
}
} 我查看STC15F2K32S 芯片的最下行的最后一个字母是C,应该不是A版的问题。 楼主下面这段函数怎么能看有没有进中断呢?在中断函数中打个log看看,才能知道到底有没有进外部中断吧!
while(1)
{
if(CAN_Flag)
{
uartSendString("into Interrupt. \r\n"); // 2 不然无法进入中断
}
else
{
uartSendString("into Interrupt. \r\n");//1 主循环必须有UART发送函数。
}
} 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
基本上不使用外部中断的
驱动 mcp2515要用的啊{:mad:} xinshui 发表于 2014-11-12 18:05
哦不好意, 代码我简化了一下。缺少些代码。
CAN_Flag = 0// 在别的文件里是默认为零。在中断里设为1....
你if和else里面串口打出来的都是同一串东西,怎么能判断到底是有木有进中断呀?你把if和else里面的串口打印函数注释掉,然后拷贝一句到你中断函数中看看会不会打印出来! 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在主函数内不起作用。或者中断内的变量赋值能问题? 总之,中断能进入, 但是不能改变主函数内的变量值, 或者影响到不能运行主函数!?
xinshui 发表于 2014-11-12 19:49
不好意思,那个代码改错了, 正确的如下。
if(CAN_Flag == 0xAA) // || ((P3 & 0x04) == 0) )
{ ...
extern unsigned char CAN_Flag;这个地方CAN_Flag有在别的地方定义过了吗?没有的话为啥用extern? {:sweat:} 是我代码没弄好,MCP2515代码部分没清理干净。造的干扰。中断没问题,使用也正常, 谢谢楼上各位的回贴,非常感谢。{:handshake:}
页:
[1]