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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/408450.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux memory cgroup的memory.move_charge_at_immigrate含义

1.内核文档 上面的例子说明&#xff1a; 最开始某个进程是在cgroup A中&#xff0c;后面要迁移到cgroup B中&#xff0c;那么进程的内存计数是否要完全迁入B中&#xff0c;就是通过memory.move_charge_at_immigrate控制&#xff0c;如果目标cgroup也就是B设置了1到该字段中&am…

DBeaver安装使用

文章目录 简介支持的数据库支持的系统 下载安装DBeaver使用修改Maven下载jar地址窗口->首选项连接->驱动->Maven配置仓库地址 选择需要连接的数据库进行连接 简介 DBeaver 是一个通用的数据库管理工具和 SQL 客户端&#xff0c;支持 MySQL, PostgreSQL, Oracle, DB2,…

进存销系统

摘 要 伴随着我国全面推动信息化的趋势&#xff0c;我国的很多行业都在朝着互联网的方向进发。商品销售行业也有很多挑战。这次论文介绍的进存销系统就是为了能够解决当前传统商品进存销存在的问题&#xff0c;使得商品进存销能够更加有效率。电商智能化管理必不可少的帮手有进…

【VIsion Master】机器视觉软件二次开发(C#版本)学习笔记

0.前言 最近接手新项目&#xff0c;用海康威视旗下的HIK ROBOT Vision Master机器视觉软件做二次开发相关的项目&#xff0c;写一篇博客记录一下学习过程。 参考视频&#xff1a;https://www.bilibili.com/video/BV1tq4y1j7RP?p1 其他参考资料&#xff1a;软件自带的开发文档…

学习2d直线拟合-2

参考文章 直线拟合算法&#xff08;续&#xff1a;加权最小二乘&#xff09;_加权拟合直线法-CSDN博客 对比了参考文中和opencv中的直线拟合权重&#xff0c;不知道理解的对不对&#xff0c;前者是权重平方&#xff0c;后者没有平方 QtWidgetsApplication1::QtWidgetsApplic…

Excel中的“块”操作

在Excel中&#xff0c;有offset、index、indirect三个对“区域”操作的函数&#xff0c;是较高版本Excel中“块”操作的利器。 (笔记模板由python脚本于2024年08月20日 19:25:21创建&#xff0c;本篇笔记适合喜欢用Excel处理数据的coder翻阅) 【学习的细节是欢悦的历程】 Pytho…

幅频特性曲线分析及使用WPF绘制

文章目录 1、一阶惯性环节的幅频特性曲线分析及绘制2、二阶系统的幅频特性曲线分析及绘制3、一般的系统4、上位机代码实现4.1 一阶惯性系统4.2 二阶系统 5、稳定裕度5.1 幅值裕度5.2 相角裕度 参考 1、一阶惯性环节的幅频特性曲线分析及绘制 这里的a和b可以根据系统的不同修改,…

网络udp及ipc内存共享

大字符串找小字符串 调试 1. 信号处理函数注册&#xff1a;•一旦使用 signal 函数注册了信号处理函数&#xff0c;该函数就会一直有效&#xff0c;直到程序结束或者显式地取消注册。2. 注册多次的影响&#xff1a;•如果多次注册同一信号的处理函数&#xff0c;最后一次注册的…

【记录】基于Windows系统安装rust环境的过程

到官网下载安装包【入门 - Rust 程序设计语言 (rust-lang.org)】 ![[Pasted image 20240703142911.png]] 选择1&#xff0c;快速安装 选择编译配置&#xff0c;1为标准 安装完成 验证是否安装完毕 rustc --versioncargo --version验证成功&#xff01;

UneMeta创始人讲述自己在Web3+IP领域创业的心路历程

昨日&#xff0c;UneMeta创始人&#xff0c;Ann_tyrion在X分享了一篇推文&#xff0c;分享了自己在探索Web3与IP产业结合过程中的心路历程&#xff0c;她并没有像很多项目方那样一味的讲述宏大的叙事&#xff0c;而是字里行间透露出对这个行业的探索和不断给自己充实信念&#…

自动操作一键数据恢复/电子取证

对磁盘模拟扫描修复丢失数据的实验。 先挂载题目磁盘VHD。 Windows系统中打开磁盘管理&#xff0c;-操作&#xff0c;-附加VHD 可以看到已经加载出题目磁盘&#xff0c;接下来打开RStudio数据恢复软件&#xff0c;对其进行扫描。 操作找回丢失/被删除的数据 可以看到已经加载出…

DRF——pagination分页模块

文章目录 分页继承APIView类用法1.PageNumberPagination2.LimitOffsetPagination3.CursorPagination 继承GenericAPIView派生类用法1.PageNumberPagination2.LimitOffsetPagination3.CursorPagination 分页 在查看数据列表的API中&#xff0c;如果 数据量 比较大&#xff0c;肯…

【前端基础篇】JavaScript之DOM介绍

文章目录 WebAPI背景知识什么是WebAPI什么是APIAPI参考文档 DOM基本概念什么是DOMDOM树查找HTML元素方法概览1. document.getElementById(id)2.document.getElementsByTagName(name)3. document.getElementsByClassName(name)4. document.querySelector(CSS选择器)5. document.…

如何免费获取乡镇级边界数据geoJson数据

如何免费获取乡镇级边界数据geoJson数据 我们可以通过 阿里云数据可视化平台 &#xff0c;可以获取到中国各个省份/区级/县级的json数据&#xff0c;但是区级和县级&#xff0c;并没有包含街道和乡镇的数据 获取乡镇级边界数据 1.下载bigemap全能版 安装好后选择你要导出的…

Graphpad Prism for Mac 医学绘图软件教程

Mac分享吧 文章目录 效果一、下载软件二、开始安装1、双击运行软件&#xff0c;将其从左侧拖入右侧文件夹中&#xff0c;等待安装完毕2、应用程序显示软件图标&#xff0c;表示安装成功 三、运行测试安装完成&#xff01;&#xff01;&#xff01; 效果 一、下载软件 下载软件…

关于jupyter notebook 的输出 (outputs )

jupyter notebook 的输出 (outputs )在元素达到一定的个数后&#xff0c;就会按一行一个元素进行展示&#xff0c;百来个还好&#xff0c;一旦过千&#xff0c;那滚轮势必撸冒烟&#xff0c;所以能不能解决呢&#xff1f; 先看个例子&#xff0c; 一个找质数、合数的函数 cal3&…

开发高质量PDF应用的不二选择:PdfiumViewer库详细解析

1. PdfiumViewer库简介 PdfiumViewer是一款基于谷歌开源PDF渲染引擎PDFium的.NET库&#xff0c;主要用于在Windows应用程序中显示和处理PDF文档。PdfiumViewer提供了多种API和控件&#xff0c;使得开发者可以轻松地将PDF文档嵌入到其应用程序中。同时&#xff0c;PdfiumViewer…

unity游戏开发——(细)深入解析 Unity 地形系统:从基础到高级应用

Unity游戏开发 “好读书&#xff0c;不求甚解&#xff1b;每有会意&#xff0c;便欣然忘食。” 本文目录&#xff1a; Unity游戏开发 Unity游戏开发前言深入解析 Unity 地形系统&#xff1a;从基础到高级应用一、初识 Unity 地形系统1. 地形尺寸与分辨率 二、地形编辑工具详解1…

kafka发送消息-自定义消息发送的拦截器

1、自定义拦截器 创建自定义拦截器类&#xff0c;实现ProducerInterceptor接口。对消息进行拦截&#xff0c;可以在拦截中对消息做些处理&#xff0c;记录日志等操作… package com.power.config;import org.apache.kafka.clients.producer.ProducerInterceptor; import org…

【Spring Boot】全局异常处理

目录 背景 前言 设计步骤 1.定义异常信息类&#xff1a; 2.自定义异常&#xff1a; 3.创建全局异常处理类 4.在控制器中抛出异常 5.输出 捕获 Valid 校验异常 背景 去面试的时候被问到SpringBoot项目中&#xff0c;如何处理全局异常的&#xff0c;也就是如何捕获全局异…