BUG——GT911上电后中断一直触发

2024-08-21 23:28

本文主要是介绍BUG——GT911上电后中断一直触发,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

版型:正点原子 I.MX6UL  MINI板 

屏幕:7寸 1024*600  ATK-MD0700R V1.4

     我的建议是买7寸屏幕就不要Mini板,因为Mini板太小装不下7寸屏幕,你需要一个更大的板子

   简介:

     算是作为一个后来者对这一现象的补充。解决方案就是在中断开启前主动清零,详情可见本篇末尾,点击目录【总结】

        具体情形是,上电之后,本应不会触发中断,结果却一直疯跳,14s左右进入1400多次中断,与扫描频率100Hz相近。

 启发:

         看了一些博客,说0x814E这个寄存器没有清零,实际上是有清零这一步的。在测试中发现,上电后虽然中断会一直触发,但只要你在屏幕上乱摸一会儿,就可以正常了。不过这显然不是什么正经的解决方案。

void GT911_read_tpcoord(void)
{uint8_t buf[4];uint8_t regvalue = 0;regvalue = GT911_read_byte(GT911_ADDR, GT_GSTID_REG);GT911_write_byte(GT911_ADDR, GT_GSTID_REG, 0x00);/*清零*/GT911_dev.point_num = regvalue & 0XF; /* 计算读取了多少个点 *//* 读取当前所有的触摸坐标值 */for (uint8_t i = 0; i < GT911_dev.point_num; ++i){GT911_read_len(GT911_ADDR, GT911_TPX_TBL[i], 4, buf); /* 读取坐标值 */GT911_dev.x[i] = ((u16)buf[1] << 8) + buf[0];GT911_dev.y[i] = (((u16)buf[3] << 8) + buf[2]);}
}volatile static uint32_t count = 0;
void GT911_irqhandler(void)
{gpio_clearintflags(GPIO1, 9); /* 清除中断标志位 */if (GT911_dev.initfalg == GT911_INIT_FINISHED){GT911_dev.intflag = 1;GT911_read_tpcoord();printf("%d\r\n", GT911_dev.point_num);for (uint8_t i = 0; i < GT911_dev.point_num; ++i){printf("X%d:%d  Y%d: %d\r\n", i, GT911_dev.x[i], i, GT911_dev.y[i]);}printf("\r\n");}printf("Interrupt:%d---------------------\r\n", ++count);
}

 尝试:

        看情形,觉得是清零不到位,于是在中断前面加了一个清零步骤,就有了双倍清零效果

volatile static uint32_t count = 0;
void GT911_irqhandler(void)
{gpio_clearintflags(GPIO1, 9); /* 清除中断标志位 */GT911_write_byte(GT911_ADDR, GT_GSTID_REG, 0x00);/*清零*/if (GT911_dev.initfalg == GT911_INIT_FINISHED){GT911_dev.intflag = 1;GT911_read_tpcoord();printf("%d\r\n", GT911_dev.point_num);for (uint8_t i = 0; i < GT911_dev.point_num; ++i){printf("X%d:%d  Y%d: %d\r\n", i, GT911_dev.x[i], i, GT911_dev.y[i]);}printf("\r\n");}printf("Interrupt:%d---------------------\r\n", ++count);
}

        结果居然真的停了,重启过几次,发现都是11次,没有变。

    为此,我就在结构体里面多添加了一个成员,专门用于清零计数。中断里面添加了个分支,用于判断是否清零了11次(不同的芯片、板子可能不同)。虽然可行,但终究多了一步,感觉有些浪费

struct GT911_dev_struct
{uint16_t x[5];     /* X轴坐标 	*/uint16_t y[5];     /* Y轴坐标 	*/uint8_t initfalg;  /* 触摸屏初始化状态 */uint8_t intflag;   /* 标记中断有没有发生 */uint8_t point_num; /* 触摸点 		*/uint8_t init_clear;
};/*--------------------中断处理函数---------------------------/void GT911_irqhandler(void)
{if (GT911_dev.init_clear < 12){GT911_write_byte(GT911_ADDR, GT_GSTID_REG, 0x00);++GT911_dev.init_clear;}else{if (GT911_dev.initfalg == GT911_INIT_FINISHED){GT911_dev.intflag = 1;GT911_read_tpcoord();printf("%d\r\n", GT911_dev.point_num);for (uint8_t i = 0; i < GT911_dev.point_num; ++i){printf("X%d:%d  Y%d: %d\r\n", i, GT911_dev.x[i], i, GT911_dev.y[i]);}printf("\r\n");}}gpio_clearintflags(GPIO1, 9); /* 清除中断标志位 */printf("Interrupt:%d---------------------\r\n", ++count);
}

         于是就想着,在GT911中断开启之后,板子中断开启之前对芯片清零,于是初始化代码变成了

    delay_ms(10);GT911_write_byte(GT911_ADDR, GT911_Command_Reg, 0);/*----------------中断前清零--------------------*/for (uint16_t i = 0; i < 15; i++){GT911_write_byte(GT911_ADDR, GT_GSTID_REG, 0x00);printf("Clear:%d---------------------\r\n", i);}
/*----------------中断前清零--------------------*/GIC_EnableIRQ(GPIO1_Combined_0_15_IRQn);                                                                                   /* 使能GIC中对应的中断 */system_register_irqhandler(GPIO1_Combined_0_15_IRQn, (system_irq_handler_t)GT911_irqhandler, NULL); /* 注册中断服务函数 */ // 放在前面,不然gpio_enableint(GPIO1, 9);delay_ms(100);GT911_dev.initfalg = GT911_INIT_FINISHED;
done:delay_ms(10);

         结果没什么效果,不过转念一想中断里面是双倍清零,问题可能就出在了这里

 于是发生了下面这一幕,虽然有效,但又不完全有。

 

         本着闲着也是闲着,后面就测试了多种情况

/*----------------中断前清零--------------------*/for (uint16_t i = 0; i < 15; i++){GT911_write_byte(GT911_ADDR, GT_GSTID_REG, 0x00);printf("Clear:%d---------------------\r\n", i);}
/*----------------中断前清零--------------------*/

 :把for循环里的printf去掉

        清零足足600次,才能清掉

:添加延时

        延时1ms,清零80次左右,可以正常清掉。进一步测试发现,延时越长所需清零次数越少。不过延时越少也意味着所耗费的时间越长,延时10ms与在中断里面清零的效果差不多,再往上20ms、50ms差距就不大了,都能在10次以内清零。50ms与100ms效果相同,达到500ms效果反而差了些,后面就没继续测了。

总结:

         中断开启前,以10ms左右的延时清零8次左右即可解决问题,当然具体情况具体讨论,在这个参考上调整一下。

    for (uint16_t i = 0; i < 8; i++){delay_ms(10);GT911_write_byte(GT911_ADDR, GT_GSTID_REG, 0x00);}

        源码在下面,都是在正点原子代码的基础上微调一下

 Touch.h源码

#ifndef __BSP_TOUCH_H
#define __BSP_TOUCH_H
#include "imx6ul.h"
/* 触摸屏结构体 */
struct GT911_dev_struct
{uint16_t x[5];     /* X轴坐标 	*/uint16_t y[5];     /* Y轴坐标 	*/uint8_t initfalg;  /* 触摸屏初始化状态 */uint8_t intflag;   /* 标记中断有没有发生 */uint8_t point_num; /* 触摸点 		*/uint8_t init_clear;
};extern struct GT911_dev_struct GT911_dev;void touch_init(void);
void GT911_read_tpcoord(void);#endif // !__BSP_TOUCH_H

Touch.c源码

#include "bsp_touch.h"
#include "bsp_gpio.h"
#include "delay.h"
#include "bsp_i2c.h"
#include "myDebug.h"
#include "bsp_int.h"#define GT911_ADDR 0x28 // 0xBA/*GT911寄存器*/
// W
// 0:读坐标状态 1:差值原始值 2:软件复位3:基准更新(内部测试) 4:基准校准(内部测试) 5 : 关屏其余值无效
#define GT911_Command_Reg 0x8040// R/W
#define GT911_Config_Version_Reg 0x8047
#define GT911_XL_Reg 0x8048
#define GT911_YL_Reg 0x8049
#define GT911_YH_Reg 0x804A
#define GT911_Touch_Number_Reg 0x804C
#define GT911_Module_Switch1_Reg 0x804D
#define GT911_Module_Switch2_Reg 0x804E
#define GT911_Shake_Count_Reg 0x804F // 手指按下/松开去抖次数
#define GT911_Filter_Reg 0x8050
#define GT911_Large_Touch_Reg 0x8051
#define GT911_Noise_Reduction_Reg 0x8052 // 噪声消除值(系数为 1,0-15 有效)#define GT911_Screen_Touch_Level_Reg 0x8053 // bit 7-0 屏上触摸点从无到有的阈值
#define GT911_Screen_Leave_Level_Reg 0x8054 // bit 7-0 屏上触摸点从有到无的阈值
#define GT911_Low_Power_Control_Reg 0x8055  // bit 3-0 进低功耗时间(0~15s)#define GT_PID_REG 0x8140
#define GT911_ID1_Reg 0x8140
#define GT911_ID2_Reg 0x8141
#define GT911_ID3_Reg 0x8142
#define GT911_ID4_Reg 0x8143#define GT_GSTID_REG 0X814E /* GT911当前检测到的触摸情况 */
#define GT_TP1_REG 0X8150   /* 第一个触摸点数据地址 */
#define GT_TP2_REG 0X8158   /* 第二个触摸点数据地址 */
#define GT_TP3_REG 0X8160   /* 第三个触摸点数据地址 */
#define GT_TP4_REG 0X8168   /* 第四个触摸点数据地址  */
#define GT_TP5_REG 0X8170   /* 第五个触摸点数据地址   */#define GT911_XYCOORDREG_NUM 30  /* 触摸点坐标寄存器数量 */
#define GT911_INIT_FINISHED 1    /* 触摸屏初始化完成 			*/
#define GT911_INIT_NOTFINISHED 0 /* 触摸屏初始化未完成 			*/// GT911模块开关寄存器
// bit 5-4  Stretch_rank
// bit 3    X2Y(X,Y坐标交换)// bit 1-0 INT输出极性选择
#define GT911_Module_Switch1_INT_RisingEdge 0x00
#define GT911_Module_Switch1_INT_FallingEdge 0x01
#define GT911_Module_Switch1_INT_LowLevel 0x02
#define GT911_Module_Switch1_INT_HighLevel 0x03void GT911_irqhandler(void);
uint8_t GT911_read_byte(uint8_t addr, uint32_t reg);
uint8_t GT911_write_byte(uint8_t addr, uint32_t reg, uint8_t data);
void GT911_write_len(uint8_t addr, uint32_t reg, uint32_t len, uint8_t *buf);
void GT911_read_len(uint8_t addr, uint32_t reg, uint32_t len, uint8_t *buf);/*变量定义*/
struct GT911_dev_struct GT911_dev;/*触摸屏初始化*/
void touch_init(void)
{IOMUXC_InitTypeDef iomuxc_init = {0};iomuxc_init.SPEED = IOMUXC_SPEED_MEDIUM;iomuxc_init.SRE = IOMUXC_SRE_Fast_Slew_Rate;iomuxc_init.DSE = IOMUXC_DSE_R0_6;iomuxc_init.HYS = IOMUXC_HYS_Enable;iomuxc_init.SION = IOMUXC_SION_Disable;IOMUXC_InitPin(IOMUXC_SNVS_SNVS_TAMPER9_GPIO5_IO09, &iomuxc_init); // CT_RSTIOMUXC_InitPin(IOMUXC_GPIO1_IO09_GPIO1_IO09, &iomuxc_init);        // CT_INTiomuxc_init.PULL = IOMUXC_PULL_PUS_47K_UP | IOMUXC_PULL_PKE_Keeper_Enable | IOMUXC_PULL_PUE_Pull;iomuxc_init.HYS = IOMUXC_HYS_Disable;iomuxc_init.SION = IOMUXC_SION_Enable;IOMUXC_InitPin(IOMUXC_UART5_TX_DATA_I2C2_SCL, &iomuxc_init);IOMUXC_InitPin(IOMUXC_UART5_RX_DATA_I2C2_SDA, &iomuxc_init);GPIO_InitTypeDef gpio_init = {0};gpio_init.Pin = GPIO_PIN_9;gpio_init.Direction = GPIO_DIR_Output;gpio_init.Output = GPIO_OUTPUT_High;// CT_INTGPIO_Init(GPIO1, &gpio_init);// CT_RSTGPIO_Init(GPIO5, &gpio_init);i2c_init(I2C2);// 0xBA设备地址的复位// GPIO_ClearPin(GPIO5, GPIO_PIN_9);// GPIO_ClearPin(GPIO1, GPIO_PIN_9);// delay_ms(10);                   // 大于100us即可// GPIO_SetPin(GPIO5, GPIO_PIN_9); // 停止复位// delay_ms(100);                  // 大于5ms即可GPIO_ClearPin(GPIO5, GPIO_PIN_9);delay_ms(10);GPIO_SetPin(GPIO5, GPIO_PIN_9); // 停止复位delay_ms(10);GPIO_ClearPin(GPIO1, GPIO_PIN_9); /* 拉低INT引脚 */delay_ms(100);/***********GT911内部配置初始化**************/GT911_dev.initfalg = GT911_INIT_NOTFINISHED;GT911_dev.point_num = 0;GT911_dev.init_clear = 0;for (uint8_t i = 0; i < 5; ++i){ /* 避免编译器自动赋值 */GT911_dev.x[i] = 0;GT911_dev.y[i] = 0;}volatile uint8_t temp[7];                                   // 一不留神就被编译器优化死了GT911_read_len(GT911_ADDR, GT_PID_REG, 6, (uint8_t *)temp); /* 读取产品ID */temp[6] = temp[4];temp[4] = 0;printf("CTP ID:%s\r\n", temp);                             /* 打印ID */printf("Default Ver:%#x\r\n", ((temp[5] << 8) | temp[6])); /* 打印固件版本 *//* 重新设置中断IO,配置为中断功能 */IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO09_GPIO1_IO09, 0x0080);gpio_init.Direction = GPIO_DIR_Input;gpio_init.InterruptMode = GPIO_INT_RisingEdge;gpio_init.Output = GPIO_OUTPUT_Low;if (temp[0] != 0x31){temp[0] = GT911_read_byte(GT911_ADDR, 0x804D) & 0x3; /* 获取中断模式 */printf("9xx\r\n");}else{temp[0] = GT911_read_byte(GT911_ADDR, 0x8056) & 0x3;}switch (temp[0]){case 0x0:printf("InterruptMode:IntRisingEdge\r\n");gpio_init.InterruptMode = GPIO_INT_RisingEdge;break;case 0x1:printf("InterruptMode:IntFallingEdge\r\n");gpio_init.InterruptMode = GPIO_INT_FallingEdge;break;case 0x2:printf("InterruptMode:IntLowLevel\r\n");gpio_init.InterruptMode = GPIO_INT_Low;break;case 0x3:printf("InterruptMode:IntHighLevel\r\n");gpio_init.InterruptMode = GPIO_INT_High;break;default:printf("InterruptMode: Error\r\n");gpio_init.InterruptMode = GPIO_INT_BothEdge;break;}GPIO_Init(GPIO1, &gpio_init);if (GT911_write_byte(GT911_ADDR, GT911_Command_Reg, 0x2)){GT911_dev.initfalg = GT911_INIT_NOTFINISHED;goto done;}delay_ms(10);GT911_write_byte(GT911_ADDR, GT911_Command_Reg, 0);for (uint16_t i = 0; i < 8; i++){delay_ms(10);GT911_write_byte(GT911_ADDR, GT_GSTID_REG, 0x00);// printf("Clear:%d---------------------\r\n", i);}GIC_EnableIRQ(GPIO1_Combined_0_15_IRQn);                                                                                   /* 使能GIC中对应的中断 */system_register_irqhandler(GPIO1_Combined_0_15_IRQn, (system_irq_handler_t)GT911_irqhandler, NULL); /* 注册中断服务函数 */ // 放在前面,不然gpio_enableint(GPIO1, 9);delay_ms(100);GT911_dev.initfalg = GT911_INIT_FINISHED;
done:delay_ms(10);
}/** @description			: GPIO1_IO9最终的中断处理函数* @param				: 无* @return 				: 无*/
volatile static uint32_t count = 0;
void GT911_irqhandler(void)
{gpio_clearintflags(GPIO1, 9); /* 清除中断标志位 */// printf("Interrupt:%d---------------------\r\n", ++count);if (GT911_dev.init_state == GT911_INIT_FINISHED){GT911_read_tpcoord();if (GT911_dev.point_num)GT911_dev.int_flag = 1;// printf("%d\r\n", GT911_dev.point_num);// for (uint8_t i = 0; i < GT911_dev.point_num; ++i)// {//     printf("X%d:%d  Y%d: %d\r\n", i, GT911_dev.x[i], i, GT911_dev.y[i]);// }// printf("\r\n");}
}/** @description	: 向GT911写入数据* @param - addr: 设备地址* @param - reg : 要写入的寄存器* @param - data: 要写入的数据* @return 		: 操作结果*/
uint8_t GT911_write_byte(uint8_t addr, uint32_t reg, uint8_t data)
{uint8_t status = 0;uint8_t writedata = data;struct i2c_transfer masterXfer;/* 配置I2C xfer结构体 */masterXfer.slaveAddress = addr;    /* 设备地址 				*/masterXfer.direction = kI2C_Write; /* 写入数据 				*/masterXfer.subaddress = reg;       /* 要写入的寄存器地址 			*/masterXfer.subaddressSize = 2;     /* 地址长度一个字节 			*/masterXfer.data = &writedata;      /* 要写入的数据 				*/masterXfer.dataSize = 1;           /* 写入数据长度1个字节			*/if (i2c_master_transfer(I2C2, &masterXfer))status = 1;return status;
}/** @description	: 从GT911读取一个字节的数据* @param - addr: 设备地址* @param - reg : 要读取的寄存器* @return 		: 读取到的数据。*/
uint8_t GT911_read_byte(uint8_t addr, uint32_t reg)
{uint8_t val = 0;struct i2c_transfer masterXfer;masterXfer.slaveAddress = addr;   /* 设备地址 				*/masterXfer.direction = kI2C_Read; /* 读取数据 				*/masterXfer.subaddress = reg;      /* 要读取的寄存器地址 			*/masterXfer.subaddressSize = 2;    /* 地址长度一个字节 			*/masterXfer.data = &val;           /* 接收数据缓冲区 				*/masterXfer.dataSize = 1;          /* 读取数据长度1个字节			*/i2c_master_transfer(I2C2, &masterXfer);return val;
}/** @description	: 从GT911读取多个字节的数据* @param - addr: 设备地址* @param - reg : 要读取的开始寄存器地址* @param - len : 要读取的数据长度.* @param - buf : 读取到的数据缓冲区* @return 		: 无*/
void GT911_read_len(uint8_t addr, uint32_t reg, uint32_t len, uint8_t *buf)
{struct i2c_transfer masterXfer;masterXfer.slaveAddress = addr;   /* 设备地址 				*/masterXfer.direction = kI2C_Read; /* 读取数据 				*/masterXfer.subaddress = reg;      /* 要读取的寄存器地址 			*/masterXfer.subaddressSize = 2;    /* 地址长度一个字节 			*/masterXfer.data = buf;            /* 接收数据缓冲区 				*/masterXfer.dataSize = len;        /* 读取数据长度1个字节			*/i2c_master_transfer(I2C2, &masterXfer);
}/** @description	: 向GT911多个寄存器写入数据* @param - addr: 设备地址* @param - reg : 要写入的开始寄存器地址* @param - len : 要写入的数据长度.* @param - buf : 写入到的数据缓冲区* @return 		: 无*/
void GT911_write_len(uint8_t addr, uint32_t reg, uint32_t len, uint8_t *buf)
{struct i2c_transfer masterXfer;masterXfer.slaveAddress = addr;    /* 设备地址         */masterXfer.direction = kI2C_Write; /* 读取数据 	    */masterXfer.subaddress = reg;       /* 要读取的寄存器地址 */masterXfer.subaddressSize = 2;     /* 地址长度一个字节     */masterXfer.data = buf;             /* 接收数据缓冲区 	    */masterXfer.dataSize = len;         /* 读取数据长度1个字节  */i2c_master_transfer(I2C2, &masterXfer);
}const uint16_t GT911_TPX_TBL[5] = {GT_TP1_REG, GT_TP2_REG, GT_TP3_REG, GT_TP4_REG, GT_TP5_REG};
/** @description	: 读取当前所有触摸点的坐标* @param 		: 无* @return 		: 无*/
void GT911_read_tpcoord(void)
{uint8_t buf[4];uint8_t regvalue = 0;regvalue = GT911_read_byte(GT911_ADDR, GT_GSTID_REG);GT911_write_byte(GT911_ADDR, GT_GSTID_REG, 0x00);GT911_dev.point_num = regvalue & 0XF; /* 计算读取了多少个点 *//* 读取当前所有的触摸坐标值 */for (uint8_t i = 0; i < GT911_dev.point_num; ++i){GT911_read_len(GT911_ADDR, GT911_TPX_TBL[i], 4, buf); /* 读取坐标值 */GT911_dev.x[i] = ((u16)buf[1] << 8) + buf[0];GT911_dev.y[i] = (((u16)buf[3] << 8) + buf[2]);}
}

iomuxc.h

#ifndef __BSP_IOMUX_H
#define __BSP_IOMUX_H
#include "fsl_iomuxc.h"// 用于简化寄存器位域的配置
#define configBits(data, bits, pos) ((data & bits) << pos)
#define ConfigBits(data, pos) (data << pos)// 迟滞功能
#define IOMUXC_HYS_POS 16
#define IOMUXC_HYS_BITS 0x1
#define IOMUXC_HYS_Disable 0x0
#define IOMUXC_HYS_Enable 0x1// 上拉/下拉功能
#define IOMUXC_PULL_POS 12
#define IOMUXC_PULL_BITS 0xF
#define IOMUXC_PULL_PUS_100K_DOWN 0x0 // 上下拉电阻配置
#define IOMUXC_PULL_PUS_47K_UP 0x4
#define IOMUXC_PULL_PUS_100K_UP 0x8
#define IOMUXC_PULL_PUS_22K_UP 0xC
#define IOMUXC_PULL_PUE_Keeper 0x0         // bit 13
#define IOMUXC_PULL_PUE_Pull 0x2           // bit 13
#define IOMUXC_PULL_PKE_Keeper_Disable 0x0 // bit 12
#define IOMUXC_PULL_PKE_Keeper_Enable 0x1  // bit 12// 开漏功能
#define IOMUXC_ODE_POS 11
#define IOMUXC_ODE_BITS 0x1
#define IOMUXC_ODE_Disable 0x0
#define IOMUXC_ODE_Enable 0x1// 速度功能
#define IOMUXC_SPEED_POS 6
#define IOMUXC_SPEED_BITS 0x3
#define IOMUXC_SPEED_LOW 0x0 // 速度配置官方手册比较模糊,就凑合配了一下
#define IOMUXC_SPEED_LOWPlus 0x1
#define IOMUXC_SPEED_MEDIUM 0x2
#define IOMUXC_SPEED_HIGH 0x3// 驱动强度功能
#define IOMUXC_DSE_POS 3
#define IOMUXC_DSE_BITS 0x7
#define IOMUXC_DSE_Output_Driver_Disable 0x0
#define IOMUXC_DSE_R0_260Ohm 0x1
#define IOMUXC_DSE_R0_2 0x2 // R0/2
#define IOMUXC_DSE_R0_3 0x3
#define IOMUXC_DSE_R0_4 0x4
#define IOMUXC_DSE_R0_5 0x5
#define IOMUXC_DSE_R0_6 0x6
#define IOMUXC_DSE_R0_7 0x7// 转换速率功能
#define IOMUXC_SRE_POS 0
#define IOMUXC_SRE_BITS 0x1
#define IOMUXC_SRE_Slow_Slew_Rate 0x0
#define IOMUXC_SRE_Fast_Slew_Rate 0x1// 复用功能
#define IOMUXC_MUX_MODE_POS 0
#define IOMUXC_MUX_MODE_BITS 0x7
#define IOMUXC_ALT_0 0x0
#define IOMUXC_ALT_1 0x1
#define IOMUXC_ALT_2 0x2
#define IOMUXC_ALT_3 0x3
#define IOMUXC_ALT_4 0x4
#define IOMUXC_ALT_5 0x5
#define IOMUXC_ALT_6 0x6
#define IOMUXC_ALT_7 0x7
#define IOMUXC_ALT_8 0x8// 软件输入功能
#define IOMUXC_SION_POS 4
#define IOMUXC_SION_BITS 0x1
#define IOMUXC_SION_Disable 0x0 // 输入路径由功能决定
#define IOMUXC_SION_Enable 0x1  // 强制输入路径typedef struct
{uint8_t PULL : 4;  // 上拉/下拉uint8_t DSE : 3;   // 驱动强度uint8_t HYS : 1;   // 迟滞uint8_t SPEED : 2; // 速度uint8_t ODE : 1;   // 开漏uint8_t SRE : 1;   // 转换速率uint8_t SION : 1;  // 软件输入
} IOMUXC_InitTypeDef;void IOMUXC_InitPin(uint32_t muxRegister,uint32_t muxMode,uint32_t inputRegister,uint32_t inputDaisy,uint32_t configRegister,IOMUXC_InitTypeDef *IOMUXC_ConfigStruct);#endif // !__BSP_IOMUX_H

iomuxc.c

#include "iomuxc.h"
void IOMUXC_InitPin(uint32_t muxRegister,uint32_t muxMode,uint32_t inputRegister,uint32_t inputDaisy,uint32_t configRegister,IOMUXC_InitTypeDef *IOMUXC_ConfigStruct)
{*((volatile uint32_t *)muxRegister) = configBits(muxMode, IOMUXC_MUX_MODE_BITS, IOMUXC_MUX_MODE_POS) |configBits(IOMUXC_ConfigStruct->SION, IOMUXC_SION_BITS, IOMUXC_SION_POS);if (inputRegister){*((volatile uint32_t *)inputRegister) = IOMUXC_SELECT_INPUT_DAISY(inputDaisy);}if (configRegister){*((volatile uint32_t *)configRegister) = configBits(IOMUXC_ConfigStruct->DSE, IOMUXC_DSE_BITS, IOMUXC_DSE_POS) |configBits(IOMUXC_ConfigStruct->HYS, IOMUXC_HYS_BITS, IOMUXC_HYS_POS) |configBits(IOMUXC_ConfigStruct->ODE, IOMUXC_ODE_BITS, IOMUXC_ODE_POS) |configBits(IOMUXC_ConfigStruct->PULL, IOMUXC_PULL_BITS, IOMUXC_PULL_POS) |configBits(IOMUXC_ConfigStruct->SPEED, IOMUXC_SPEED_BITS, IOMUXC_SPEED_POS) |configBits(IOMUXC_ConfigStruct->SRE, IOMUXC_SRE_BITS, IOMUXC_SRE_POS);}
}

这篇关于BUG——GT911上电后中断一直触发的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1094590

相关文章

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

FreeRTOS学习笔记(四)Freertos的中断管理及临界保护

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、Cortex-M 中断管理1.1 中断优先级分组1.2 相关寄存器1.3 相关宏定义1.4 FreeRTOS 开关中断 二、临界段及其保护2.1 taskENTER_CRITICAL( ) 和 taskEXIT_CRITICAL( )2.2 taskENTER_CRITICAL_FROM_ISR( )

Cortex-A7:ARM官方推荐的嵌套中断实现机制

0 参考资料 ARM Cortex-A(armV7)编程手册V4.0.pdf ARM体系结构与编程第2版 1 前言 Cortex-M系列内核MCU中断硬件原生支持嵌套中断,开发者不需要为了实现嵌套中断而进行额外的工作。但在Cortex-A7中,硬件原生是不支持嵌套中断的,这从Cortex-A7中断向量表中仅为外部中断设置了一个中断向量可以看出。本文介绍ARM官方推荐使用的嵌套中断实现机

外部中断的边缘触发和电平触发

MCS-51单片机中的边缘触发是指当输入引脚电平由高到低发生跳变时,才引起中断。而电平触发是指只要外部引脚为低电平就引起中断。         在电平触发方式下,当外部引脚的低电平在中断服务返回前没有被拉高时(即撤除中断请求状态),会引起反复的不需要的中断,造成程序执行的错误。这类中断方式下,需要在中断服务程序中设置指令,清除外部中断的低电平状态,使之变为高电平。

【Java编程思想】线程的基本协作机制 与 线程的中断

wait/notify Java在Object类中定义了一些线程协作的基本方法,wait和notify public final void wait() throws InterruptedException;public final native void wait(long timeout) throws InterruptedException; 一个带时间参数,单位是毫秒,表示最

基于IMX6ULL的Cortex-A中断原理讲解,以及编写其中断向量表

首先借助STM32我们需要了解中断系统是如何构成的         会有一个中断源,也就是能够向CPU发出中断请求的设备或事件。中断源不分硬件和软件,也就是产生中断信号,就会执行中断服务函数         但是CPU是如何知道中断源产生后就找到对应的中断服务函数呢,这个时候就要引入中断向量表,它的主要功能是描述中断对应的中断服务函数,每个中断源都有一个唯一的中断号(也称向量号),

【银河麒麟高级服务器操作系统实例】虚拟化平台系统服务中断现象分析及处理建议

服务器环境以及配置 【机型】虚机 处理器: Kunpeng-920 内存: 40G 【内核版本】 4.19.90-23.8.v2101.ky10.aarch64 【OS镜像版本】 银河麒麟操作系统 Kylin-Server-10-SP1-Release-Build20-20210518-arm64 【第三方软件】 智能运维系统、mysql数据集群 现象描述 环境描

ASP.NET手动触发页面验证控件事件

开发环境:.NET Framework 3.5.1 sp1 参考文章: http://www.codeproject.com/KB/aspnet/JavascriptValidation.aspx http://msdn.microsoft.com/zh-cn/library/aa479045.aspx http://www.cnblogs.com/minsentinel/archive/

JavaBug系列-解决SpringBoot返回Xml结构的问题

JavaBug系列之SpringBoot返回Xml结构的问题 Java医生一、关于错误信息二、如何解决问题 Java医生 本系列记录常见Bug,以及诊断过程和原因 作者:Java医生 教学: Java企业项目辅导,专注于辅导新入职员工,解决各种问题! V:study_51ctofx 一、关于错误信息 如图,SpringBoot请求返回Xml格式信息 通过以上信息分析,

JavaBug系列- Failed to load driver class com.mysql.cj.jdbc.Driver in either of HikariConfig class load

JavaBug系列之Mysql驱动问题 Java医生一、关于错误信息二、如何解决问题 Java医生 本系列记录常见Bug,以及诊断过程和原因 Java/一对一零基础辅导/企业项目一对一辅导/日常Bug解决/代码讲解/毕业设计等 V:study_51ctofx 一、关于错误信息 APPLICATION FAILED TO START Description: Fai