ARM920T实验箱s3c2410 矩阵按键控制步进电机正反转和停止

ARM920T实验箱s3c2410 矩阵按键控制步进电机正反转和停止

问题描述

按下第一个按键使步进电机可以正转、第二个反转反转、第三个按键停止

矩阵按键控制

画了张矩阵按键的内部电路图:

请添加图片描述

矩阵按键实物图:
请添加图片描述

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)

通过给电机地址赋值即可实现正反转:

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);
 }

完整代码

本文是通过轮循的方式扫描按键是否被按下,完整代码如下:


#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;
            }
            
        }
    }
}
  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LrvinOen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值