- #include <reg52.h>
- signed long beats = 0; //电机转动节拍总数
- void KeyDriver();
- void main()
- {
- EA = 1; //使能总中断
- TMOD = 0x01; //设置T0为模式1
- TH0 = 0xFC; //为T0赋初值0xFC67,定时1ms
- TL0 = 0x67;
- ET0 = 1; //使能T0中断
- TR0 = 1; //启动T0
-
- while (1)
- {
- KeyDriver(); //调用按键驱动函数
- }
- }
- /* 步进电机启动函数,angle-需转过的角度 */
- void StartMotor(signed long angle)
- {
- //在计算前关闭中断,完成后再打开,以避免中断打断计算过程而造成错误
- EA = 0;
- beats = (angle * 4076) / 360; //实测为4076拍转动一圈
- EA = 1;
- }
- /* 步进电机停止函数 */
- void StopMotor()
- {
- EA = 0;
- beats = 0;
- EA = 1;
- }
- /* 按键动作函数,根据键码执行相应的操作,keycode-按键键码 */
- void KeyAction(unsigned char keycode)
- {
- static bit dirMotor = 0; //电机转动方向
-
- if ((keycode>=0x30) && (keycode<=0x39)) //控制电机转动1-9圈
- {
- if (dirMotor == 0)
- StartMotor(360*(keycode-0x30));
- else
- StartMotor(-360*(keycode-0x30));
- }
- else if (keycode == 0x26) //向上键,控制转动方向为正转
- {
- dirMotor = 0;
- }
- else if (keycode == 0x28) //向下键,控制转动方向为反转
- {
- dirMotor = 1;
- }
- else if (keycode == 0x25) //向左键,固定正转90度
- {
- StartMotor(90);
- }
- else if (keycode == 0x27) //向右键,固定反转90度
- {
- StartMotor(-90);
- }
- else if (keycode == 0x1B) //Esc键,停止转动
- {
- StopMotor();
- }
- }
- /* 按键驱动函数,检测按键动作,调度相应动作函数,需在主循环中调用 */
- void KeyDriver()
- {
- unsigned char i, j;
- static unsigned char backup[4][4] = { //按键值备份,保存前一次的值
- {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}
- };
-
- for (i=0; i<4; i++) //循环检测4*4的矩阵按键
- {
- for (j=0; j<4; j++)
- {
- if (backup[i][j] != KeySta[i][j]) //检测按键动作
- {
- if (backup[i][j] != 0) //按键按下时执行动作
- {
- KeyAction(KeyCodeMap[i][j]); //调用按键动作函数
- }
- backup[i][j] = KeySta[i][j]; //刷新前一次的备份值
- }
- }
- }
- }
- /* 电机转动控制函数 */
- void TurnMotor()
- {
- unsigned char tmp; //临时变量
- static unsigned char index = 0; //节拍输出索引
- unsigned char code BeatCode[8] = { //步进电机节拍对应的IO控制代码
- 0xE, 0xC, 0xD, 0x9, 0xB, 0x3, 0x7, 0x6
- };
-
- if (beats != 0) //节拍数不为0则产生一个驱动节拍
- {
- if (beats > 0) //节拍数大于0时正转
- {
- index++; //正转时节拍输出索引递增
- index = index & 0x07; //用&操作实现到8归零
- beats--; //正转时节拍计数递减
- }
- else //节拍数小于0时反转
- {
- index--; //反转时节拍输出索引递减
- index = index & 0x07; //用&操作同样可以实现到-1时归7
- beats++; //反转时节拍计数递增
- }
- tmp = P1; //用tmp把P1口当前值暂存
- tmp = tmp & 0xF0; //用&操作清零低4位
- tmp = tmp | BeatCode[index]; //用|操作把节拍代码写到低4位
- P1 = tmp; //把低4位的节拍代码和高4位的原值送回P1
- }
- else //节拍数为0则关闭电机所有的相
- {
- P1 = P1 | 0x0F;
- }
- }
- /* T0中断服务函数,用于按键扫描与电机转动控制 */
- void InterruptTimer0() interrupt 1
- {
- static bit div = 0;
-
- TH0 = 0xFC; //重新加载初值
- TL0 = 0x67;
- KeyScan(); //执行按键扫描
- //用一个静态bit变量实现二分频,即2ms定时,用于控制电机
- div = ~div;
- if (div == 1)
- {
- TurnMotor();
- }
- }
复制代码 |