📄 pwm.c
字号:
// 该程序利用EVA模块的PWM1--PWM4引脚产生不同占空比的方波调节直流电机的电压
#include "C2407A.h"
#include "stdio.h"
#define Tc_half 2000
#define KEY1_run 0X0F3D //电动机正向转动(按奇数次),正向制动(按偶数次)
#define KEY1_stop 0X0F37 //电动机反向转动(按奇数次),反向转动(按偶数次)
#define KEY2_run 0X0FD3 //电动机加速“+”
#define KEY2_stop 0X0F73 //电动机减速“-”
#define stop 0X0FFF // 0000 1111 1111 1111 全部输出强制为高
int Ton=1000; //声明一个外部变量
int K1,K2,K3,K4=0;
int key1,key2,key3,key4=0;
int flag=0;
int initial()
{
asm(" setc INTM"); //DISABLE_INTS();
asm(" setc SXM"); // 符号位扩展有效
asm(" clrc OVM"); // 累加器中结果正常溢出
asm(" clrc CNF"); // B0被配置为数据存储空间
*SCSR1=0x0304; // CLKIN=20M,CLKOUT=2*CLKIN=40M
*WDCR=0x0e8; // 不使能看门狗,因为SCSR2中的WDOVERRIDE
// 即WD保护位复位后的缺省值为1,故可以用
// 软件禁止看门狗
*IMR=0x02; // 禁止所有中断
*IFR=0xFF; // 清除全部中断标志,"写1清0"
WSGR=0X0000; // 禁止所有的等待状态
}
// 定时器1的初始化子程序
int timer1int()
{
*EVAIMRA=*EVAIMRA|0X0200; // 允许定时器1的下溢中断
*EVAIFRA=*EVAIFRA&0X0200; // 清除定时器1 下溢中断标志
*EVAIMRB=0X0000 ; // 屏蔽所有事件管理器中断?
*EVAIMRC=0X0000;
*T1CNT=0X00; // Timer1的计数器清零
}
// EVA模块的PWM初始化程序
int pwminitial()
{
*MCRA=*MCRA|0X0fc0; // 被配置为基本功能方式,PWM1-6
*ACTRA=stop; // PWM6,4,2 高有效,PWM5,3,1 低有效0000
*DBTCONA=0X05F4; // 使能死区控制
*CMPR1=Ton;
*CMPR2=Ton;
*T1PR=2000; // 设置定时器1的周期寄存器,并设置CMPR1-3,以确定不
// 同的输出占空比
*COMCONA=0X8200; // 使能比较操作
*T1CON=0X0842; // 定时器1为连续增减
}
// 定时器1下溢中断服务程序 设定好占空比初始值设为1000
void interrupt GISR2( )
{
extern Ton;
flag=*EVAIFRA&0X0200;
if(flag!=0x0200)
{
asm(" clrc INTM"); //ENABLE_INTS( ); // 允许总中断
return; // 如果不是定时器1周期中断,则直接返回
}
// 如果是定时器1周期中断定时器1的周期中断,则执行下面的产生pwm程序
*EVAIFRA=*EVAIFRA&0X0200; // 清除定时器1 下溢中断标志
asm(" clrc INTM");//ENABLE_INTS( ); // 允许总中断,因一进中断服务程序后总中断就自动关闭了
return ; // 中断返回
}
// 但可能由于干扰会引起他们的执行,故该中断服务程序无额外操作,直接返回
void interrupt nothing( )
{
asm(" clrc INTM");//ENABLE_INTS( ); // 允许总中断,因一进中断服务程序后总中断就自动关闭了
return; // 中断返回
}
void inline ENABLE_INTS( ) //开总中断
{
asm(" clrc INTM");
}
//void inline DISABLE_INTS() //关总中断
//{
// asm(" setc INTM ");
//}
// 键扫描程序
int keyscan()
{ extern K1,K2,K3,K4;
extern key1,key2,key3,key4;
K1=key;//asm("IN K1,0007h");
K2=key;//asm("IN K2,0007h");
K3=key;//asm("IN K3,0007h");
K4=key;//asm("IN K4,0007h");
//K1
if(K1&&0X0001==0||K2&&0X0002||K3&&0X0004||K4&&0X0008)
{
delay(); //去抖
K1=key;//asm("IN K1,0007h");
K2=key;//asm("IN K2,0007h");
K3=key;//asm("IN K3,0007h");
K4=key;//asm("IN K4,0007h");
if(K1&&0X0001==0)
key1=(key1+1)%2; //键1按下
if(K2&&0X0002==0)
key2=(key2+1)%2; //键2按下
if(K3&&0X0001==0)
key3=1; //键3按下
if(K4&&0X0002==0)
key4=1; } //键4按下
//返回键值
return;
}
//首先检测KEY3,KEY4有无变化 如有变化进入去抖环节并记录下来 对应的变量和上下限比较后加减1,返回一个Ton值
//然后检查KEY1,KEY2有无变化 KEY1,KEY2检测到的新值与原值做如下运算
//比如KEY0初值为0,按了一次后 KEY0=((0+1)%2)=1 有正向制动改为正向运行
// KEY0初值为1,按了一次后 KEY0=((1+1)%2)=0 由正向运行改为正向制动
int delay()
{
int i;
for(i=0;i++;i<5000){i=i;}
}
// 主程序
void main()
{ extern key1,key2,key3,key4; //定义四个键的初值
int t=0;
initial(); // 系统初始化
timer1int(); // 定时器1的初始化
pwminitial(); //pwm初始化
asm(" clrc INTM");//ENABLE_INTS(); // 允许总中断
while(1)
{ keyscan();
if(key1==1)
{*ACTRA=KEY1_run ; //电动机正向转动(按奇数次)
for(;;)
{
keyscan();
if(key1==0)
{
*ACTRA=KEY1_stop; //电动机正向制动(按偶数次)
break;
}
else if(key3==1||t<20) //分为20档 电机转速有20个档位
{t=t+1;} //每个档位差为0.6v电压差,对应占空比100/2000;
else if(key4==1||t>0)
{t=t-1;}
*CMPR1=200*t;
*CMPR2=200*t;
}
}
else if(key2==1)
{*ACTRA=KEY2_run; //电动机反向转动(按奇数次)
for(;;)
{
keyscan();
if(key2==0)
{
*ACTRA=KEY2_stop; //电动机反向制动(按偶数次)
break;
}
else if(key3==1||t<20) //分为20档 电机转速有20个档位
{t=t+1;} //每个档位差为0.6v电压差,对应占空比100/2000;
else if(key4==1||t>0)
{t=t-1;}
*CMPR1=200*t;
*CMPR2=200*t;
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -