• slider image 514
  • slider image 516
  • slider image 517
  • slider image 518
  • slider image 519
:::


Browsing this Thread:   1 Anonymous Users






[求助]PIC30f2010+IR2011+HC595+1602控制器,PIC的PDC1、2、3寄存器怎么变成调时基了?不是调占空比的吗?(附程序)
#1
新會員
新會員


查看用戶資訊
最近在做无刷电机控制器,用了PIC30f2010,也参考了官方的例子。开机运行时要慢慢启转动的,我是控制PDC的值,先为0再一直加到512。这个功能是行的,但是在过流时要把占空比调小,就是转速要慢,让它电流值在那个范围内,我是这样做的,一当有电流超过设定值就减一个PDC的值,电流如果没有到设定值就加一个PDC值,可到那运行时却变成调时基了,PDC的值为512时是没有时基的,511就有一点点时基了,时基频率是设定值,但脉冲很窄。这个值越小时基就越多,PDC明明是调占空比的怎么会变成调时基(PWM)去了呢?程序如下:写的有点乱,也比较笨,别见笑!

//----------------------------------------------------------------------
//**************** 振荡器 ************************************
//#define dFoscExt 5 000 000 // 外部晶振或时钟频率(Hz)
//#define dPLL 8 // PLL 比率
//#define dLoopTimeInSec 0.00005 // PWM 周期 - 100 uS, 10Khz PWM
//#define dDeadTimeSec 0.000 002 // 以秒为单位的死区时间
// Derived
//#define dFosc (5 000 000*8) // 时钟频率(Hz)
//#define dFcy (40 000 000/4) // 指令频率(Hz)
//#define dTcy (1.0/10 000 000) // 指令周期(s)=0.000 000 1s=100ns
//#define dDeadTime (int)(0.000 002*10 000 000) // 以dTcys 为单位的死区时间=0.000 000 000 0002
//#define dLoopInTcy (dLoopTimeInSec/dTcy) // 以Tcy 为单位的基本循环周期
//#define dDispLoopTime 0.100 // 显示和按钮状态查询循环

#include "p30F2010.h"
_FOSC(0x0c306); //XT振荡,4倍频晶振.
_FWDT(WDT_OFF); //关闭看门狗定时器
_FBORPOR(PBOR_OFF & MCLR_EN); //掉电复位禁止,MCLR复位使能。
_FGS(CODE_PROT_OFF); //代码保护禁止
#define FCY 10000000// xtal = 5.0Mhz ; PLLx8
#define MILLISEC FCY/10000// 1 mS 延迟常数
#define FPWM 39000
#define S2 LATCbits.LATC14
#define EN2 LATCbits.LATC13
#define RS2 LATDbits.LATD0 //15
#define HC595_SCLK LATDbits.LATD1 //14
#define HC595_SID LATFbits.LATF2 //18
#define HC595_enable LATFbits.LATF3 //17

void InitTMR3(void);
void InitADC10(void);
void AverageADC(void);
void DelayNmSec(unsigned int N);
void InitMCPWM(void);
void CalculateDC(void);
void GetSpeed(void);
struct {
unsigned RunMotor : 1;
unsigned Minus : 1;
unsigned xsbit : 1; //0.5S显示一次
unsigned Ysbit : 1; //电机刚起的时候的延时
unsigned tdybit : 1; //太低压了保护
unsigned dzbit : 1; //堵转的位
unsigned dlbit : 1; //短路的位
unsigned zfbit : 1; //正反转的位
unsigned addybit : 1; //ad低压
unsigned adglbit : 1; //ad过流
unsigned unused : 6;
} Flags;
unsigned int HallValue;
unsigned int Ys; //刚开电机时电压和电流不检测延时一下
unsigned int ysmoto,glms; //慢起动
unsigned int glys;
unsigned int gl[10];
unsigned int dy[10];
unsigned int dybit;
unsigned int glbit;
unsigned int i,j,k,l,m;
unsigned long glnum,dynum;
unsigned long vmoto,zsmoto,zsbit,zsjs;
unsigned char ZF[ ]={'U',':','.','V',' ','B','A','T','%','R','P','M'};
unsigned int test;
unsigned int dzbf,dzbfjs; //堵转保护
unsigned int ADAD,state;
/************************************************************/
void delay(unsigned int i)
{
while(i--);
}
/*************************************************************
以下是低端驱动器表。在此StateLoTable 中,
在低端驱动器施加PWM 信号,而高端驱动器为“导通”或“截止”状态。
在本练习中使用此表。
*************************************************************/
unsigned int StateLoTable[] = {0x0000, 0x02001, 0x0810, 0x0801,0x0204, 0x2004, 0x0210, 0x0000};
/****************************************************************
以下是变化通知引脚CN5、CN6 和CN7 的中断向量。
当霍尔传感器改变状态时,将引起中断,指令执行将转到下面的子程序。
然后用户必须读端口B 的第3 位、第4 位和第5 位,
对读到的值进行移位和调节以使之读作1、2……6。
然后将调整后的值用作查找表StateLoTable 中的偏移量
以确定装入OVDCON 寄存器的值。
*****************************************************************/
void _ISR _CNInterrupt(void)
{
IFS0bits.CNIF = 0; // 清零标志
HallValue = PORTB & 0x0038; // 屏蔽其它位,保留RB3、RB4 和RB5
HallValue = HallValue >> 3; // 执行3 次右移
OVDCON = StateLoTable[HallValue];
zsbit++;
dzbf=0;
//if(HallValue==1)
//S2=!S2;
}
/*********************************************************************
ADC 中断用给定的电位计值装载PDCx 寄存器。
仅在电机运行时执行此操作。
*********************************************************************/
void _ISR _ADCInterrupt(void)
{
IFS0bits.ADIF = 0;
if (Flags.RunMotor)
{
//ADAD=ADCBUF0>>1;
//ADAD=ADAD-ysmoto-glms;
//PDC1 = ADAD; // 赋值……>>等于/2笨蛋
//PDC2 = PDC1; // 并装载所有的三个PWM……
//PDC3 = PDC1; // 占空比寄存器

if(Flags.addybit==0){
dy[dybit]=ADCBUF1;
if(dybit++>=8)
{
dybit=0;Flags.addybit=1;
}
}

if(Flags.adglbit==0){
gl[glbit]=ADCBUF2;
if(glbit++>=8)
{
glbit=0;Flags.adglbit=1;
}
}
}
}
/*********************************************************************
外中断,下降沿触发,短路保护
*********************************************************************/
void _ISR _INT0Interrupt(void)
{
IFS0bits.INT0IF = 0;
//PWMCON1 = 0x0700; // 禁止PWM 输出
//OVDCON = 0x0000; // 将PWM 改写为低电平
Flags.RunMotor = 0; // 复位运行标志
Flags.dlbit=1;
}
/*******************************************************************************************************************/
//发送一个字节(底层函数)
void lcm_w_byte(unsigned char bbyte) {
unsigned char i;
for(i=0;i<8;i++){
HC595_SID=bbyte&0x01; //取出最高位
DelayNmSec(1);
HC595_SCLK=0;
DelayNmSec(1);
HC595_SCLK=1;
bbyte>>=1; //左移
HC595_enable=0;
DelayNmSec(1);
HC595_enable=1;
DelayNmSec(1);
}
}
/*************************************/
void enable2(void)
{
EN2=1; //E=1;
DelayNmSec(1); //当系统时钟为1MHz时,延时ns
EN2=0; //E=0;
}
/****************************指令*****************************/
void writecmd2(unsigned char command)
{
unsigned char command_temp;

command_temp = command;

RS2=0; //命令;
DelayNmSec(1);
lcm_w_byte(command_temp);
enable2();
DelayNmSec(1);
RS2=1;
}
/*******************************数据*******************************/
void writedata2(unsigned char Adata)
{
unsigned char data_temp;

data_temp = Adata;
EN2=0;
DelayNmSec(1);
RS2=1;
DelayNmSec(12);
lcm_w_byte(data_temp);
DelayNmSec(1);
enable2();
}

/*****************************位址*****************************/
void setcoordinate2(unsigned char x,unsigned char y)
{
unsigned char address;
if (y == 0) address = 0x80 + x;
else
address = 0xc0 + x;
writecmd2(address);
}
/**************************送字符**************************/
void writestring2(unsigned char X,unsigned char Y,unsigned char s)
{
setcoordinate2(X, Y);
writedata2(s);
}
/******************************************************/
void initLCD2(void)
{
writecmd2(0x38); //4bit 只要改成38就为8位
DelayNmSec(2);
enable2();
DelayNmSec(2);
writecmd2(0x38); //4bit
DelayNmSec(2);
writecmd2(0x0c); //显示开
DelayNmSec(2);
writecmd2(0x01); //显示清屏
DelayNmSec(2);
writecmd2(0x06); //显示光标移动设置
DelayNmSec(2);
}
/************************************************************************
**Tmr1初始化函数
*************************************************************************/
void InitTMR1(void)
{
T1CON=0x0010; // internal Tcy/256 clock
TMR1=0xcf2c;
PR1=0xffff; //16 16*62=1ms
IFS0bits.T1IF=0; //清除TMR1的中断标志
IEC0bits.T1IE=1; //使能中断

}
/*******************计算电压和电流***********************/
void js(void)
{
unsigned char i;
if (Flags.RunMotor)
{
if(Flags.addybit){
for(i=0;i<8;i++)
dynum+=dy[i];
dynum=dynum>>3;
vmoto=dynum;
if(dynum<372) //低压
{
Flags.RunMotor = 0; // 复位运行标志
Flags.tdybit=1;
} //如果电压小于20V的话继电器关
dynum=0;
Flags.addybit=0;
}

if(Flags.adglbit){
for(i=0;i<8;i++)
glnum+=gl[i];
glnum=glnum>>3;
if(glnum>=512) //抗干拢一下明天再试--10=4ms
{
glms--;
if(glms<20) glms=20; //电流到这时转速就慢下来,
}
else
{
glms++;
if(glms>510) glms=510;
}
glnum=0;
test = glms;
PDC1 = glms; // 赋值------------------------这就是处理电流后去给PDC寄存器的值,可是却变成调时基了(39K的载波)
PDC2 = glms; // 并装载所有的三个PWM……
PDC3 = glms;
Flags.adglbit=0;
}
}
}
/********************************************************
**定时器1中断服务
*********************************************************/
//void __attribute__((__interrupt__)) _T1Interrupt(void)
void _ISR _T1Interrupt(void)
{
TMR1=0xcf2c;
IFS0bits.T1IF = 0; //清定时器中断标志
if (Flags.RunMotor) //10ms
{
zsjs++;
if(zsjs>=50)
{
S2=!S2;js();
Flags.xsbit=1;
zsjs=0;
zsmoto=zsbit*60/24*2;
zsbit=0;
}

dzbf++;
if(dzbf>=200) //如果超过两秒就认为堵转
{
dzbf=0;
Flags.dzbit=1;
Flags.RunMotor=0;
}
}
}
/*******************************************************************************************************************/
int main(void)
{
TRISC = 0x9FFF;
TRISD = 0x0000;
TRISF = 0x0000;
LATD = 0xFFFF;
LATF = 0xFFFF;
LATE = 0x0000;
TRISE = 0xFFC0; // 设置为输出PWM 信号
CNEN1 = 0x00E0; // 使能CN5、CN6 和CN7
CNPU1 = 0x00E0; // 使能内部上拉
InitMCPWM();
InitADC10();
initLCD2();
InitTMR1();
INTCON2bits.INT0EP = 1;
IFS0bits.INT0IF = 0;
IEC0bits.INT0IE = 1;
IFS0bits.CNIF = 0; // 清零CNIF
IEC0bits.CNIE = 1; // 允许CN 中断
glms=511;
//Flags.Ysbit = 0;
//Flags.gjbit = 1;
//DelayNmSec(1000);
S2=1; //打开继电器
DelayNmSec(1000); //3s
//DelayNmSec(100); //100ms
// 在PORTB 上读霍尔位置传感器
HallValue = PORTB & 0x0038; // 屏蔽其它位,保留RB3、RB4 和RB5
HallValue = HallValue >> 3; // 右移以获得值1、2……6
OVDCON = StateLoTable[HallValue]; // 装载改写控制寄存器
PWMCON1 = 0x0777; // 使能PWM 输出
T1CONbits.TON = 1;
for(ysmoto=0;ysmoto<510;ysmoto++)
{
DelayNmSec(2);
PDC1 = ysmoto; // 赋值------------------开机慢慢启动,这是行的,可以改变速度。
PDC2 = PDC1; // 并装载所有的三个PWM……
PDC3 = PDC1;
}
ysmoto=0x0000;
Flags.RunMotor = 1; // 将标志置1

/*****************/
while(1)
{
DelayNmSec(100);
while (Flags.RunMotor) // 当电机运行时
{
//if(Flags.xsbit){
//Flags.xsbit=0;
test=vmoto;
//vmoto=vmoto*550/1024;
writestring2(0,0,ZF[0]);
writestring2(1,0,ZF[1]);
writedata2((vmoto*550/1024/100)%10+48);
writedata2((vmoto*550/1024/10)%10+48);
writestring2(4,0,ZF[2]);
writedata2((vmoto*550/1024%10)+48);
writestring2(6,0,ZF[3]);
writestring2(7,0,ZF[4]);
writestring2(8,0,ZF[5]);
writestring2(9,0,ZF[6]);
writestring2(10,0,ZF[7]);
writestring2(11,0,ZF[7]);
writestring2(12,0,ZF[1]);
writedata2(((vmoto*550/1024*10)/360)%10+48);
writedata2(((vmoto*550/1024*10)/36)%10+48);
writestring2(15,0,ZF[8]);
writestring2(0,1,ZF[9]);
writestring2(1,1,ZF[10]);
writestring2(2,1,ZF[11]);
writestring2(3,1,ZF[1]);
writedata2((zsmoto/1000)%10+48);
writedata2((zsmoto/100)%10+48);
writedata2((zsmoto/10)%10+48);
writedata2(zsmoto%10+48);
//DelayNmSec(200);
//writestring2(8,1,ZF[4]);//AD
//writedata2((test/1000)%10+48);
writedata2((test/100)%10+48);
writedata2((test/10)%10+48);
writedata2(test%10+48);
//writedata2((zsbit/1000)%10+48);
//writedata2((zsbit/100)%10+48);
//writedata2((zsbit/10)%10+48);
//writedata2(zsbit%10+48);*/
//}
}
if((Flags.dlbit==1)||(Flags.dzbit==1))//如果短路堵转
{
PWMCON1 = 0x0700; // 禁止PWM 输出
OVDCON = 0x0000; // 将PWM 改写为低电平
DelayNmSec(1);
//while(l<30)
//{
while(k<1200)//k为展开速度
{
for(j=0;j<25;j++)
{
if(j<=i)
LATE=0xffea;
else
LATE=0xffc0;
}k++;
}i++;k=0;
//if(i>=20) {i=20;l++;}
//}
//这里要显示什么故障
state=0;
while(1){ //死循环
if(Flags.dlbit) state=1;
if(Flags.dzbit) state=2;
//if(Flags.dlbit) state=3;
//if(Flags.dlbit) state=4;
writestring2(13,1,state%10+48);
}
}
}
}
/*******************************************************************
以下代码用于设置ADC 寄存器,该代码可实现下列功能:
1. 1 个通道转换( 本例中,该通道为RB2/AN2)
2. PWM 触发信号启动转换
3. 电位计连接到CH0 和RB2
4. 手动停止采样和启动转换
5. 手动检查转换完成
*********************************************************************/
void InitADC10(void)
{
ADPCFG = 0xFFF8; // 将端口B 的RB0 到RB2 配置为模拟引脚;将其它引脚配置为数字引脚
ADCON1 = 0x0064; // PWM 启动转换
ADCON2 = 0x0208; // 同时采样4 个通道
ADCHS = 0x0002; // 将RB2/AN2 作为CH0 连接到电位计……
// ch1 连接母线电压、Ch2 连接电机, Ch3 连接电位计
ADCON3 = 0x0080; // Tad 来源于内部RC (4uS)
IFS0bits.ADIF = 0;
IEC0bits.ADIE = 1;
ADCON1bits.ADON = 1; // 启动ADC
}
/********************************************************************
InitMCPWM,对PWM 做以下初始化:
1. FPWM = 39000 hz
2. 独立的PWM
3. 使用OVDCON 控制输出
4. 用从电位计读取的ADC 值设置占空比
5. 将ADC 设置为由PWM 特殊触发信号触发
*********************************************************************/
void InitMCPWM(void)
{
PTPER = FCY/FPWM - 1;
PWMCON1 = 0x0700; // 禁止PWM
OVDCON = 0x0000; // 允许使用OVD 控制
PDC1 = 100; // 将PWM1、PWM2 和PWM3 初始化为100
PDC2 = 100;
PDC3 = 100;
//SEVTCMP = PTPER;
PWMCON2 = 0x0F00; // 后分频比设为1:16
PTCON = 0x8000; // 启动PWM
}
//---------------------------------------------------------------------
// 这是普通的1 ms 延迟程序,用于提供1 mS 到65.5 秒的延迟。
// 如果N = 1,则延迟为1 mS ;如果N = 65535,则延迟为65,535 mS。
// 注意FCY 用于计算。
// 请根据上述定义语句做出必要的更改(PLLx4 或PLLx8 等)
// 以计算出正确的FCY。
void DelayNmSec(unsigned int N)
{
unsigned int j;
while(N--)
for(j=0;j < MILLISEC;j++);
}

發表於: 2009/6/23 18:29
Twitter Facebook Google Plus Linkedin Del.icio.us Digg Reddit Mr. Wong 頂部







You can view topic.
不可以 發起新主題
You cannot reply to posts.
You cannot edit your posts.
You cannot delete your posts.
You cannot add new polls.
You cannot vote in polls.
You cannot attach files to posts.
You cannot post without approval.
You cannot use topic type.
You cannot use HTML syntax.
You cannot use signature.
You cannot create PDF files.
You cannot get print page.

[進階搜尋]


:::

Microchip連結

https://www.facebook.com/microchiptechnologytaiwan/
http://www.microchip.com.tw/modules/tad_uploader/index.php?of_cat_sn=13
https://mu.microchip.com/page/tmu
http://elearning.microchip.com.tw/modules/tad_link/index.php?cate_sn=1
https://page.microchip.com/APAC-PrefCenters-TW.html
http://www.microchip.com/
http://www.microchip.com/treelink
http://www.microchipdirect.com/
http://www.microchip.com.cn/newcommunity/index.php?m=Video&a=index&id=103
http://www.microchip.com.tw/modules/tad_uploader/index.php?of_cat_sn=2
http://www.microchip.com.tw/Data_CD/eLearning/index.html
http://www.microchip.com.tw/RTC/RTC_DVD/
https://www.microchip.com/development-tools/
https://www.youtube.com/user/MicrochipTechnology
[ more... ]

教育訓練中心

!開發工具購買
辦法說明 [業界客戶] [教育單位]
----------------------------------
!校園樣品申請
辦法說明 [教師資格] [學生資格]
----------------------------------