LV.12 D16 轮询与中断 学习笔记-CSDN博客
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
一、CPU与硬件的交互方式
轮询
CPU执行程序时不断地询问硬件是否需要其服务若需要则给予其服务若不需要一段时间后再次询问周而复始
中断
CPU执行程序时若硬件需要其服务对应的硬件给CPU发送中断信号CPU接收到中断信号后将当前的程序暂停下来转而去执行中断服务程序执行完成后再返回到被打断的点继续执行
DMA
硬件产生数据后硬件控制器可将产生的数据直接写入到存储器中整个过程无需CPU的参与
二、轮询方式实现按键实验
先找到K2按键。
正常状态下UART_RING是高电平当K2按下变成低电平松手以后重新变回高电平。
使用GPIO的输入功能来检测引脚的电平状态。
#include "exynos_4412.h"
int main()
{
/*将GPX1_1设置成输入功能*/
GPX1.CON = GPX1.CON & (~(0xF << 4));
while(1)
{
if(!(GPX1.DAT & (1 << 1)))
{
printf("Key2 Pressed\n");
}
else
{
}
}
return 0;
}
CPU执行速度很快所以K2按键按一下就会打印出很多"Key2 Pressed"
#include "exynos_4412.h"
int main()
{
/*将GPX1_1设置成输入功能*/
GPX1.CON = GPX1.CON & (~(0xF << 4));
while(1)
{
/*判断GPX1_1引脚的状态即判断按键是否按下*/
if(!(GPX1.DAT & (1 << 1)))
{
printf("Key2 Pressed\n");
/*等待松手*/
while(!(GPX1.DAT & (1 << 1)));
}
else
{
}
}
return 0;
}
此时K2按键按一下只会打印一边"Key pressed"
三、GPIO中断相关寄存器详解
如果把GPX0设置成中断功能后中断的细节就在以下带40的里设置GPX1对应41依次类推。
GPX1_1对应EXT_INT41_CON[1]用于管理和配置中断相关功能。
设置中断触发方式
0x1低电平可以触发信号
0x2高电平可以触发信号
0x3下降沿可以触发信号即从高电平变为低电平时
0x4上升沿可以触发信号即从低电平变为高电平时
0x5上升沿或下降沿都可以触发信号
本次实验使用的是K2按键① 如果使用低电平触发方式可能会多次触发中断。② 如果使用高电平触发方式我们没按下K2按键时就处于高电平状态即会一直发送中断信号。③ 使用下降沿触发方式没有问题还可以避免按一次就触发好几次中断。④ 设置成上升沿则松手时会触发信号。⑤ 设置成双边沿按一次会触发两次。
EXT_INT41_FLTCON1是滤波寄存器因为手可能会抖导致产生奇怪的波形这个电路会把波形变成我们想要的。(本次实验不使用)
EXT_INT41_MASK用于设置中断的开关每一位对应一个引脚也就是EXT_INT41_MASK[1]对应GPX1_1的开和关。0x0打开中断0x1关闭中断。
EXT_INT41_PEND是挂起寄存器,由于CPU在执行别的中断时会自动屏蔽同时给他发送到中断信号为了不丢失这个信号我们可以使用挂起功能在CPU做别的东西时我们把信号挂起等CPU空闲了我们在发送信号。这个寄存器一般不用自己写引脚产生中断后会自动置1
四、GPIO中断编程
中断挂起寄存器当有中断产生时会自动置1当中断处理完后我们需要把它置0.本次实验暂时不设置
#include "exynos_4412.h"
int main()
{
/*将GPX1_1设置成中断功能*/
GPX1.CON = GPX1.CON | (0xF << 4);
/*设置GPX1_1中断触发方式下降沿触发*/
EXT_INT41_CON = EXT_INT41_CON & (~(0x7 << 4)) | (0x2 << 4);
/*使能GPX1_1的中断功能*/
EXT_INT41_MASK = EXT_INT41_MASK & (~(1 << 1));
return 0;
}
作业
使用轮询的方式检测Key3按键的状态实现按一次按键LED2点亮再次按下LED2熄灭
#include "exynos_4412.h"
int main()
{
/*将GPX2_7设置成输出功能LED2*/
GPX2.CON = GPX2.CON & (~(0xF << 28)) | (1 << 28);
/*将GPX1_2设置成输入模式K3*/
GPX1.CON = GPX1.CON | (~(0xF << 8));
while(1)
{
/*判断GPX1_2引脚的状态即判断按键是否按下*/
if(!(GPX1.DAT & (1 << 2)))
{
/*判断LED3当前的状态*/
if(!(GPX2.DAT & (1 << 7)))
GPX2.DAT = GPX2.DAT | (0x1 << 7);
else
GPX2.DAT = GPX2.DAT & (~(0x1 << 7));
/*等待松手*/
while(!(GPX1.DAT & (1 << 2)));
}
else
{
}
}
return 0;
}