qxs5264 发表于 2009-7-8 09:53:51

flyunlimit 飞行无极限-以及PIC高手来帮忙,关于PIC单片机引脚电平中断问题。。。

本来用PIC12F683做个PID控制直流电机的,我用GP4作为脉冲输入引脚,GP5作为输出引脚,奇怪的是一直没有动作,一直没有产生中断。期待高手帮忙查看,谢谢!
/*
每圈4个脉冲
*/

#include <pic.h>
#include <pic12f683.h>

#define DAT                        GPIO0
#define CLK                        GPIO1
#define PWM                        GPIO2
#define KEY                        GPIO3
#define SPEED_IN        GPIO4
#define SH_CP                GPIO5

#define uchar         unsigned char
#define uint                 unsigned int

#define Com_Addr        0x00
#define TMR0_Value        0x10

#define         vT0_10mS        40
#define         vT0_100mS        10
#define         vT0_1S                10
#define         vT0_1Min                60
#define         vT0_1Hour        60
#define         vT0_10Hour        10

uchar        cT0_10mS;
uchar        cT0_100mS;
uchar        cT0_1S;
uchar        cT0_1Min;
uchar        cT0_1Hour;
uchar        cT0_10Hour;

uint                PreStep;//预设步长
uint                CurStep;//现有步长

uchar        cStep;
uchar        cCount;

__CONFIG(UNPROTECT & BOREN & MCLRDIS & PWRTEN & WDTEN& INTIO);

/**************************************************************************
*    函数原型: void delay(uint time)
*    功    能: 延时n mS
**************************************************************************/
void Delay_mS(uchar time){
        uchar i;
        for(;time > 0;time--){
                CLRWDT();
                i=196;
                while(i--);
        }
}

/**************************************************************************
*    函数原型: void DATA_WRITE(uchar ADDR, uchar DATA)
*    功               能: 写EEPROM
**************************************************************************/
void DATA_WRITE(uchar ADDR, uchar DATA){
        WREN = 1;
        EEADR = ADDR;
        EEDATA = DATA;
        EECON2 = 0x55;
        EECON2 = 0xaa;
        WR = 1;
}

/**************************************************************************
*    函数原型: uchar DATA_READ(uchar ADDR)
*    功               能: 读EEPROM
**************************************************************************/
uchar DATA_READ(uchar ADDR){
        EEADR = ADDR;
        RD = 1;
        return(EEDATA);
}

/**************************************************************************
*    函数原型: void ParaInit(void)
*    功               能: 系统初始化
**************************************************************************/
void ParaInit(void){
        TMR0                    = TMR0_Value;
        cT0_10mS         = vT0_10mS;
        cT0_100mS         = vT0_100mS;
        cT0_1S                 = vT0_1S;
        cT0_1Min         = vT0_1Min;
        cT0_1Hour        = vT0_1Hour;
        cT0_10Hour         = vT0_10Hour;       
}

/**************************************************************************
*    函数原型: void InitSys(void)
*    功               能: 系统初始化
**************************************************************************/
void InitSys(void){
        ParaInit();
        INTCON                = 0x00;
        OPTION                = 0x0f;
        ANSEL                = 0x00;
        GPIO                 = 0x00;               
        CMCON0                = 0x07;       
        ADCON0                = 0x00;
        TRISIO                 = 0x18;                               
        WPU                 = 0x18;       
        IOC                         = 0x10;        //允许IOC4中断
        T1CON                   = 0x00;
/*
1. 通过将相关TRIS置1来禁止PWM引脚(CCP1)输出驱动电平。
2. 装载 PR2 寄存器,以设置PWM 周期。
3. 使用适当的值装载CCP1CON 寄存器,以配置CCP1 模块使之工作于PWM 模式。
4. 装载CCPR1L 寄存器和CCP1CON 寄存器的DC1B 位,以设置PWM 占空比。
5. 配置并启动Timer2:
        . 将PIR1 寄存器的中断标志位TMR2IF 清零。
        . 装载T2CON 寄存器的T2CKPS 位,以设置Timer2 预分频比的值。
        . 通过将 T2CON寄存器的TMR2ON位置1,以使能Timer2。
6. 启动新的PWM 周期后使能PWM 输出:
        . 等待直到Timer2 溢出(PIR1 寄存器的TMR2IF 位置1)。
        . 将相关TRIS 位清零以使能CCP1 引脚输出驱动电平。
*/       
//设置PWM模式步骤...见P82页       
        TRISIO2                = 1;                        //禁止PWM引脚(CCP1)输出驱动电平
        PR2                        = 0x19;                //10KHz//装载 PR2 寄存器,以设置PWM 周期
//        CCP1CON        = 0x0f;                //PWM高两位为0,PWM输出低电平
        CCP1CON        = 0x0d;                //PWM高两位为0,PWM输出高电平
        CCPR1L                = 0x09;
                                                        //装载CCPR1L 寄存器和CCP1CON 寄存器的DC1B 位,以设置PWM 占空比
//配置并启动Timer2       
        TMR2IF                 = 0;
        T2CON                = 0x00;                //装载T2CON 寄存器的T2CKPS 位,以设置Timer2 预分频比的值
        TMR2                 = 0xff;
        TMR2ON                = 1;                        //使能Timer2
//启动新的PWM 周期后使能PWM 输出       
        TRISIO2                = 0;       
        GPIF                 = 0;
        GPIE                = 1;
        GPIO                 = GPIO;
        T0IE                        = 1;
        PEIE                        = 1;
        GIE                        = 1;
}

/**************************************************************************
*    函数原型: void main(void)
*    功               能: 主程序
**************************************************************************/
void main(void){
        InitSys();
        while(1){
                CLRWDT();
        }
}

/**************************************************************************
*    函数原型: void interrupt INTServe(void)
*    功               能: 中断处理
**************************************************************************/
void interrupt INTServe(void){
        if(GPIF == 1){
                GPIO = GPIO;
                GPIF = 0;
                SH_CP = !SH_CP;
                cCount++;
        }
       
        if(T0IF){                //定时器0是否溢出
                T0IF = 0;
                TMR0 = TMR0_Value;

                if(--cT0_10mS == 0x00){
                        cT0_10mS = vT0_10mS;       

                        if(--cT0_100mS == 0x00){
                                cT0_100mS =vT0_100mS;
                                if(--cT0_1S == 0x00){
                                        cT0_1S = vT0_1S;       
/*                                       
cStep++;
if(cStep >= 0x09){
        cStep = 0x00;
}

CCPR1L = cStep;
*/
                                        if(--cT0_1Min== 0x00){
                                                cT0_1Min = vT0_1Min;       

                                                if(--cT0_1Hour== 0x00){
                                                        cT0_1Hour= vT0_1Hour;       

                                                        if(--cT0_10Hour== 0x00){
                                                                cT0_10Hour = vT0_10Hour;       
                                                               
                                                        }
                                                }
                                        }
                                }
                        }
                }
        }
}

/**************************************************************************
*    函数原型: END
*    功               能: END
**************************************************************************/

qxs5264 发表于 2009-7-8 10:36:45

顶顶!再不顶就沉下去了,高手们,快出来呀!都开会去了?

qxs5264 发表于 2009-7-8 14:03:46

郁闷中。。。大家都没有用过电平变化中断了吗?有用过帮帮忙啊!

qxs5264 发表于 2009-7-8 21:47:14

真的没有人弄过吗?

waltonzxh 发表于 2009-7-8 23:08:29

没用过c写pic,可以这样写?位操作?
      T0IE                        = 1;
      PEIE                        = 1;
      GIE                         = 1;

qxs5264 发表于 2009-7-10 08:33:25

可以这样写。

piccode 发表于 2009-7-10 17:08:05

没有具体用过这个型号。但要仔细确认下面的
是ANALOG还是数字引脚--(一定要设定)
有没有和比较器共用。 TRISX 也要设定

-------------------------------------
花花草草先不要。
   让GPIO先接个LED。看输出可为可用先

qxs5264 发表于 2009-7-10 17:19:35

楼上,关于初始化设置那一块儿我确认一点问题都没有,这次完全按手册来操作,因为我曾今吃亏过,现在中断根本就没有进去呀。

flyunlimit 发表于 2009-7-11 16:10:48

我pic用的也不是很熟。楼这这样点名,真是让我很紧张。

端口变化中断的一般没什么好注意的,就是要每次进中断后都读一下端口,保证单片机记下这次的电平,后面一有变化就能触发了

不过这里写成这样:GPIO = GPIO;

是不是不太妥当?1、软件编译时认为没意义优化掉。2、自己写自己,总觉的有问题。你改成
void interrupt INTServe(void)
{
char i;
if(GPIF == 1)
{
   i=GPIO;

试试。i没大用,仅保证确实是读了,然后看下编译结果,保证这句没有被优化掉。PICC对无意义语句的优化是很厉害的。

qxs5264 发表于 2009-7-13 08:59:44

哎!没用,等一段时间再折腾看看!

qxs5264 发表于 2009-7-17 10:40:19

问题已解决,各位,不好意思,因为芯片只有两片,我舍不得用,用的这一块还是拆下来的,不知道是不是拆坏了,后面软件仿真都可以,实在没辙了只好换最后一块芯片,一换上去就OK了,不好意思,总是犯这样的低级错误,不好意思。

qxs5264 发表于 2009-7-17 10:44:49

我现在越来越发现我所搞不定的一些错误都是低级错误,可能是电工的通病,哈哈。经常这样,真他妈郁闷!!!

120542121 发表于 2014-10-15 21:05:45

好像是要读一遍端口的
页: [1]
查看完整版本: flyunlimit 飞行无极限-以及PIC高手来帮忙,关于PIC单片机引脚电平中断问题。。。