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
**************************************************************************/ 顶顶!再不顶就沉下去了,高手们,快出来呀!都开会去了? 郁闷中。。。大家都没有用过电平变化中断了吗?有用过帮帮忙啊! 真的没有人弄过吗? 没用过c写pic,可以这样写?位操作?
T0IE = 1;
PEIE = 1;
GIE = 1; 可以这样写。 没有具体用过这个型号。但要仔细确认下面的
是ANALOG还是数字引脚--(一定要设定)
有没有和比较器共用。 TRISX 也要设定
-------------------------------------
花花草草先不要。
让GPIO先接个LED。看输出可为可用先 楼上,关于初始化设置那一块儿我确认一点问题都没有,这次完全按手册来操作,因为我曾今吃亏过,现在中断根本就没有进去呀。 我pic用的也不是很熟。楼这这样点名,真是让我很紧张。
端口变化中断的一般没什么好注意的,就是要每次进中断后都读一下端口,保证单片机记下这次的电平,后面一有变化就能触发了
不过这里写成这样:GPIO = GPIO;
是不是不太妥当?1、软件编译时认为没意义优化掉。2、自己写自己,总觉的有问题。你改成
void interrupt INTServe(void)
{
char i;
if(GPIF == 1)
{
i=GPIO;
试试。i没大用,仅保证确实是读了,然后看下编译结果,保证这句没有被优化掉。PICC对无意义语句的优化是很厉害的。 哎!没用,等一段时间再折腾看看! 问题已解决,各位,不好意思,因为芯片只有两片,我舍不得用,用的这一块还是拆下来的,不知道是不是拆坏了,后面软件仿真都可以,实在没辙了只好换最后一块芯片,一换上去就OK了,不好意思,总是犯这样的低级错误,不好意思。 我现在越来越发现我所搞不定的一些错误都是低级错误,可能是电工的通病,哈哈。经常这样,真他妈郁闷!!! 好像是要读一遍端口的
页:
[1]