问题描述
按下第一个按键使步进电机可以正转、第二个反转反转、第三个按键停止
矩阵按键控制
画了张矩阵按键的内部电路图:
矩阵按键实物图:
ABC
按键右边的就是步进电机。
按键第一行连接的是寄存器GPFDAT0
的端口
第二行连接的是寄存器GPFDAT2
的端口
第三行连接的是寄存器GPGDAT3
的端口
第四行连接的是寄存器GPGDAT11
的端口
GPF寄存器是8个位;GPG、GPE寄存器是16位。每种寄存器还对应有GPCON控制寄存器和GPUP上拉电阻寄存器。这里可以不用配置GP*UP上拉电阻。
GP*CON控制寄存器:00输入,01输出,10中断,11保留
思路
将行配置为输入,列配置为输出。因为行连接电源,在按键没被按下时是高电平,按下后行的电平变为列电平值。
//按键,列的地址,低四位控制 #define KEY_LINE (*(volatile unsigned short*)0x38001002)
检测分三步:
1、将行配置为输入,列配置为输出。
2、首先将列全部置0,检测行是否位0,是则说明这一行有按键被按下;
3、再将一列置0,其余三列置1,检测行是否位0,是则说明这行这列的按键被按下。若不是,再将第二列置0,其余三列置1,再检测行是否为0。剩余两列也一样。
配置输入输出
void KeyInit() //按键初始化
{
//00为输入,01为输出
//输入
GPFCON=(GPECON & (~(0x3<<0)));//初始化GPF0为输入
GPFCON=(GPECON & (~(0x3<<4)));//初始化GPF2为输入
GPGCON=(GPGCON & (~(0x3<<6)));//初始化GPG3、GPG11为输入
GPGCON=(GPGCON & (~(0x3<<22)));
//输出
GPECON=(GPECON & (~(0x3<<6)));
GPECON=(GPECON | (0x1<<6));//初始化GPE3为输出
GPECON=(GPECON & (~(0x3<<22)));
GPECON=(GPECON | (0x1<<22));//初始化GPE11为输出
GPGCON=(GPGCON & (~(0x3<<4)));
GPECON=(GPECON | (0x1<<4));//初始化GPG2为输出
GPGCON=(GPGCON & (~(0x3<<12)));
GPECON=(GPECON | (0x1<<12));//初始化GPG6为输出
}
按键扫描
//*
*按键扫描函数
*/
unsigned int KeyNum()
{
//初始化不为0~15就都行
//0000
column(0);
if((GPFDAT & 0X01) == 0)
{
delay_ms(20);//消抖
//0111
column(1);
if((GPFDAT & 0X01) == 0) // key7被按下
{
delay_ms(20);
return Key = SEVEN;
}
else
column(2); //1011
if((GPFDAT & 0X01) == 0) //key8被按下
{
delay_ms(20);
return Key = EIGHT;
}
else
column(3);//1101
if((GPFDAT & 0X01) == 0) //key9 被按下
{
delay_ms(20);
return Key= NINE;
}
else
column(4);//1110
if((GPFDAT & 0X01) == 0) //keyA 被按下
{
delay_ms(20);
return Key= A;
}
}
else if ((GPFDAT & 0x04) == 0)//第二行
{
delay_ms(20);//消抖
//0111
column(1);
if((GPFDAT & 0x04) == 0) // key4被按下
{
delay_ms(20);
return Key = FOUR;
}
else
column(2);//1011
if((GPFDAT & 0x04) == 0) //key5被按下
{
delay_ms(20);
return Key = FIVE;
}
else
column(3);//1101
if((GPFDAT & 0x04) == 0) //key6 被按下
{
delay_ms(20);
return Key= SIX;
}
else
column(4);//1110
if((GPFDAT & 0x04) == 0) //keyB 被按下
{
delay_ms(20);
return Key= B;
}
}
else if ((GPGDAT & 0x0008) == 0) //第三行
{
delay_ms(20);//消抖
//0111
column(1);
if((GPGDAT & 0x0008) == 0) // key1被按下
{
delay_ms(20);
return Key = ONE;
}
//1011
else
column(2);
if((GPGDAT & 0x0008) == 0) //key2被按下
{
delay_ms(20);
return Key = TWO;
}
else//1101
column(3);
if((GPGDAT & 0x0008) == 0) //key3 被按下
{
delay_ms(20);
return Key= THREE;
}
//1110
else
column(4);
if((GPGDAT & 0x0008) == 0) //keyC 被按下
{
delay_ms(20);
return Key= C;
}
}
else if ((GPGDAT & 0x0800) == 0) //第四行
{
delay_ms(20);//消抖
//0111
column(1);
if((GPGDAT & 0x0800) == 0) // key0被按下
{
delay_ms(20);
return Key = ZERO;
}
else//1011
column(2);
if((GPGDAT & 0x0800) == 0) //keyF被按下
{
delay_ms(20);
return Key = F;
}
//1101
else
column(3);
if((GPGDAT & 0x0800) == 0) //keyE 被按下
{
delay_ms(20);
return Key= E;
}
//1110
else
column(4);
if((GPGDAT & 0x0800) == 0) //keyD 被按下
{
delay_ms(20);
return Key= D;
}
}
return Key;
}
步进电机控制
步进电机有A、B、 C、 D
四个相,分别对应四个位,正向依次通电(A->B->C->D)
即可实现正转;反向依次通电即可实现反转(D->C->B->A)
。
注意:每次通电一个相后,需要给一点延迟。
步进电机地址:0x38001000
以如下方式定义地址后:#define DIANJI (*(volatile unsigned short*)0x38001000)
通过给电机地址赋值即可实现正反转:文章来源:https://www.toymoban.com/news/detail-484871.html
unsigned short shuju[4] = {0x01, 0x02, 0x04, 0x08};
unsigned int i, j;
//步进电机正转
for (i = 0; i < 4; i++)
{
DIANJI = shuju[i];
delay_ms(100);
}
//步进电机反转
for (j = 4; j > 0; j--)
{
DIANJI = shuju[j-1];
delay_ms(100);
}
完整代码
本文是通过轮循的方式扫描按键是否被按下,完整代码如下:文章来源地址https://www.toymoban.com/news/detail-484871.html
#include <stdio.h>
//定义键盘数字值
#define ZERO 0
#define ONE 1
#define TWO 2
#define THREE 3
#define FOUR 4
#define FIVE 5
#define SIX 6
#define SEVEN 7
#define EIGHT 8
#define NINE 9
#define A 10
#define B 11
#define C 12
#define D 13
#define E 14
#define F 15
#define KEY_INIT 20 //按键初始化的值,只要不是0~15就行
/*定义步进电机地址*/
#define DIANJI (*(volatile unsigned short*)0x38001000)
//按键,列的地址,通过低四位控制
#define KEY_LINE (*(volatile unsigned short*)0x38001002)
/*定义IO端口地址*/
#define GPFCON (*(volatile unsigned *)0x56000050) //Port F control
#define GPFDAT (*(volatile unsigned *)0x56000054) //Port F data
#define GPFUP (*(volatile unsigned *)0x56000058) //Pull-up control F
#define GPGCON (*(volatile unsigned *)0x56000060) //Port G control
#define GPGDAT (*(volatile unsigned *)0x56000064) //Port G data
#define GPGUP (*(volatile unsigned *)0x56000068) //Pull-up control G
#define GPECON (*(volatile unsigned *)0x56000040) //Port E control
#define GPEDAT (*(volatile unsigned *)0x56000044) //Port E data
#define GPEUP (*(volatile unsigned *)0x56000048) //Pull-up control E
//控制步进电机正反转的数据
/**
* 电机有A、B、C、D四个相,对应四个位,分别给每个相通电。
*/
unsigned short shuju[4] = {0x01, 0x02, 0x04, 0x08};
//定义按键扫描获取的返回变量
unsigned int Key = KEY_INIT;
/**
*12MHz
* N ms延时
*/
void delay_ms(unsigned int n)
{
unsigned int i=0,j=0;
for(i=0;i<n;i++)
for(j=0;j<123;j++);
}
//延时n秒
void delay_s(unsigned int n)
{
unsigned int i=0,j=0;
for(i=0;i<n;i++)
for(j=0;j<21738;j++);
}
void KeyInit() //按键初始化
{
//00为输入,01为输出
//输入
GPFCON=(GPECON & (~(0x3<<0)));//初始化GPF0为输入
GPFCON=(GPECON & (~(0x3<<4)));//初始化GPF2为输入
GPGCON=(GPGCON & (~(0x3<<6)));//初始化GPG3、GPG11为输入
GPGCON=(GPGCON & (~(0x3<<22)));
//输出
GPECON=(GPECON & (~(0x3<<6)));
GPECON=(GPECON | (0x1<<6));//初始化GPE3为输出
GPECON=(GPECON & (~(0x3<<22)));
GPECON=(GPECON | (0x1<<22));//初始化GPE11为输出
GPGCON=(GPGCON & (~(0x3<<4)));
GPECON=(GPECON | (0x1<<4));//初始化GPG2为输出
GPGCON=(GPGCON & (~(0x3<<12)));
GPECON=(GPECON | (0x1<<12));//初始化GPG6为输出
}
//电机停止
void dj_stop()
{
DIANJI = 0;
delay_ms(100);
}
/**
*逐列扫
*
* column表示需要置0的列
* 0表示四列全置0
* 1 -> 第一列为0,其余为1
* 2 -> 第二列为0,其余为1
* 3 -> 第三列为0,其余为1
* 4 -> 第四列为0,其余为1
*/
void column(unsigned int column)
{
switch (column) {
case 0:
//0000
KEY_LINE = 0x00;
break;
case 1:
//0111
KEY_LINE = 0x0e;
break;
case 2:
//1011
KEY_LINE = 0x0d;
break;
case 3:
//1101
KEY_LINE = 0x0b;
break;
case 4:
//1110
KEY_LINE = 0x07;
default:
//1111
KEY_LINE = 0x0F;
break;
}
}
/*
*按键扫描函数
*/
unsigned int KeyNum()
{
//初始化不为0~15就都行
//0000
column(0);
if((GPFDAT & 0X01) == 0)
{
delay_ms(20);//消抖
//0111
column(1);
if((GPFDAT & 0X01) == 0) // key7被按下
{
delay_ms(20);
return Key = SEVEN;
}
else
column(2); //1011
if((GPFDAT & 0X01) == 0) //key8被按下
{
delay_ms(20);
return Key = EIGHT;
}
else
column(3);//1101
if((GPFDAT & 0X01) == 0) //key9 被按下
{
delay_ms(20);
return Key= NINE;
}
else
column(4);//1110
if((GPFDAT & 0X01) == 0) //keyA 被按下
{
delay_ms(20);
return Key= A;
}
}
else if ((GPFDAT & 0x04) == 0)//第二行
{
delay_ms(20);//消抖
//0111
column(1);
if((GPFDAT & 0x04) == 0) // key4被按下
{
delay_ms(20);
return Key = FOUR;
}
else
column(2);//1011
if((GPFDAT & 0x04) == 0) //key5被按下
{
delay_ms(20);
return Key = FIVE;
}
else
column(3);//1101
if((GPFDAT & 0x04) == 0) //key6 被按下
{
delay_ms(20);
return Key= SIX;
}
else
column(4);//1110
if((GPFDAT & 0x04) == 0) //keyB 被按下
{
delay_ms(20);
return Key= B;
}
}
else if ((GPGDAT & 0x0008) == 0) //第三行
{
delay_ms(20);//消抖
//0111
column(1);
if((GPGDAT & 0x0008) == 0) // key1被按下
{
delay_ms(20);
return Key = ONE;
}
//1011
else
column(2);
if((GPGDAT & 0x0008) == 0) //key2被按下
{
delay_ms(20);
return Key = TWO;
}
else//1101
column(3);
if((GPGDAT & 0x0008) == 0) //key3 被按下
{
delay_ms(20);
return Key= THREE;
}
//1110
else
column(4);
if((GPGDAT & 0x0008) == 0) //keyC 被按下
{
delay_ms(20);
return Key= C;
}
}
else if ((GPGDAT & 0x0800) == 0) //第四行
{
delay_ms(20);//消抖
//0111
column(1);
if((GPGDAT & 0x0800) == 0) // key0被按下
{
delay_ms(20);
return Key = ZERO;
}
else//1011
column(2);
if((GPGDAT & 0x0800) == 0) //keyF被按下
{
delay_ms(20);
return Key = F;
}
//1101
else
column(3);
if((GPGDAT & 0x0800) == 0) //keyE 被按下
{
delay_ms(20);
return Key= E;
}
//1110
else
column(4);
if((GPGDAT & 0x0800) == 0) //keyD 被按下
{
delay_ms(20);
return Key= D;
}
}
return Key;
}
void Main()
{
unsigned int key, i, j;
KeyInit();
while (1)
{
key = KeyNum();
if (key != KEY_INIT) //按键有被按下
{
switch (key) //按下的是那颗按键
{
case SEVEN:
//步进电机正转
for (i = 0; i < 4; i++)
{
DIANJI = shuju[i];
delay_ms(100);
}
break;
case EIGHT:
//步进电机反转
for (j = 4; j > 0; j--)
{
DIANJI = shuju[j-1];
delay_ms(100);
}
break;
case NINE:
dj_stop();
break;
default:
dj_stop();
break;
}
}
}
}
到了这里,关于ARM920T实验箱s3c2410 矩阵按键控制步进电机正反转和停止的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!