目录
一、CPU与硬件的交互方式
1.1轮询
1.2中断
1.3DMA
二、轮询方式的按键实验
三、GPIO中断相关寄存器
四、GPIO中断编程
五、小作业
一、CPU与硬件的交互方式
1.1轮询
CPU执行程序时不断地询问硬件是否需要其服务,若需要则给予其服务,若不需要一段时间后再次询问,周而复始。
1.2中断
CPU执行程序时若硬件需要其服务,对应的硬件给CPU发送中断信号,CPU接收到中断信号后将当前的程序暂停下来,转而去执行中断服务程序,执行完成后再返回到被打断的点继续执行。
1.3DMA
硬件产生数据后,硬件控制器可将产生的数据直接写入到存储器中,整个过程无需CPU的参与.
二、轮询方式的按键实验
#include "exynos_4412.h"
int main()
{
GPX1.CON = GPX1.CON & (~(0xF << 4));
while(1)
{
if(!(GPX1.DAT & (1<<1)))
{
printf("Key2 Pressed\n");
}
else
{
}
}
return 0;
}
由于按键抖动按一次打印了一堆。还有CPU速度太快的原因我手还没抬起来,while已经执行好几圈了。这个问题已经老生常谈了,毕竟只要是这种机械按键就会有这个问题,所以老规矩,写个松手检测。
#include "exynos_4412.h"
int main()
{
GPX1.CON = GPX1.CON & (~(0xF << 4));
while(1)
{
if(!(GPX1.DAT & (1<<1)))
{
printf("Key2 Pressed\n");
while(!(GPX1.DAT & (1<<1)));
}
else
{
}
}
return 0;
}
结果大部分都是正常的,偶尔会有按一下出来两个的情况,我们加个按键消抖,就是延时一小会儿。
#include "exynos_4412.h"
void delay(unsigned int time)
{
while(time --);
}
int main()
{
GPX1.CON = GPX1.CON & (~(0xF << 4));
while(1)
{
if(!(GPX1.DAT & (1<<1)))
{
delay(1000);
printf("Key2 Pressed\n");
while(!(GPX1.DAT & (1<<1)));
}
else
{
}
}
return 0;
}
但是这个延时不能写太大,否则会有漏掉按下动作的现象,这次我按了20多次没有重复和漏掉的现象发生。因为CPU执行1000条指令的时间没有人能按下两次,在这中间按下一次,会存在寄存器中我们循环回来还是可以读到的。
三、GPIO中断相关寄存器
三星的手册写的不是很人性化,在设置成中断功能后,配置信息隔的有些远
设置触发信号低电平、高电平、下降沿、上升沿、上升沿和下降沿一共五种。
低电平触发可能按一次触发几次中断,高电平的话由于一直接上拉电阻那就和我们要的效果相反了,下降沿没有问题还可以避免按一次触发好几次的问题,上升沿松手时触发,双边沿按一次触发两次。
设置滤波电路用的寄存器,因为手可能会抖导致产生奇怪的波形这个电路会把波形变成我们想要的。
控制中断开关的寄存器
挂起寄存器,由于CPU在执行别的中断时会自动屏蔽同时给他发送到中断信号,为了不丢失这个信号,三星为我们提供了挂起功能,在CPU做别的东西时我们把信号挂起,等CPU空闲了我们在发送信号。
四、GPIO中断编程
暂时不需要设置挂起,因为会自动挂起,只是在中断服务程序中最后要清楚这个标志。
#include "exynos_4412.h"
int main()
{
GPX1.CON = GPX1.CON | (0xF << 4);
EXT_INT41_CON = EXT_INT41_CON & (~(0x7 << 4)) | (0x2 << 4);
EXT_INT41_MASK = EXT_INT41_MASK & (~(1 << 1));
return 0;
}
先简单初始化一下GPIO的硬件设置,中断信号到CPU还有一段距离下篇文章再来继续介绍。
五、小作业
使用轮询的方式检测Key3按键的状态,实现按一次按键,LED2点亮,再次按下,LED2熄灭
#include "exynos_4412.h"
void delay(unsigned int time)
{
while(time --);
}
int main()
{
GPX1.CON = GPX1.CON & (~(0xF << 8));
GPX2.CON = GPX2.CON & (~(0xF << 28)) | (0x1 << 28);//LED2
while(1)
{
if(!(GPX1.DAT & (1<<2)))
{
delay(1000);
printf("Key3 Pressed\n");
GPX2.DAT = GPX2.DAT | (1 << 7);//LED2_ON
while(!(GPX1.DAT & (1<<2)));
}
else
{
GPX2.DAT = GPX2.DAT & (~(1 << 7));//LED2_OFF
}
}
return 0;
}
现在是按下亮松手灭,我在改良一下:
#include "exynos_4412.h"
void delay(unsigned int time)
{
while(time --);
}
int main()
{
GPX1.CON = GPX1.CON & (~(0xF << 8));
GPX2.CON = GPX2.CON & (~(0xF << 28)) | (0x1 << 28);//LED2
unsigned int flag;
while(1)
{
if(!(GPX1.DAT & (1<<2)))
{
delay(1000);
printf("Key3 Pressed\n");
if(flag == 1)
{
GPX2.DAT = GPX2.DAT | (1 << 7);//LED2_ON
flag = 0;
}else
{
GPX2.DAT = GPX2.DAT & (~(1 << 7));//LED2_OFF
flag = 1;
}
while(!(GPX1.DAT & (1<<2)));
}
else
{
}
}
return 0;
}
这次没啥问题了。