MCP23017

本文介绍了MCP23017芯片的高速I2C接口特性,适用于3.3V和5V电源。讨论了寄存器配置,特别是IOCON寄存器中的中断功能。提供了STM32使用HAL库的代码示例,包括输出实验和中断读取实验,但遇到了读取端口值的问题。作者提出了可能的解决策略,如使用DMA或临界段保护I2C操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原理图

注:模块和控制器的需要使用同一个电源
在这里插入图片描述

features

1、High-Speed I2C Interface (MCP23017):

  • 100 kHz
  • 400 kHz
  • 1.7 MHz

2、3.3V,5V都可

寄存器

官网历程用的也是bank0的
在这里插入图片描述在这里插入图片描述

寄存器 作用 使用 默认
IODIR 控制pin输入输出 1输入,0输出 输入
IPOL 控制输入引脚的极性反转 1,反应引脚的反相值 0,不反转
GPINTEN 使能对应的pin输入中断(与DEFVAL and INTCON配套使用) 1使能中断,0不使能 不使能
DEFVAL 比较值(引脚值与这个值不同则发生中断) 0
INTCON 设置比较方式 为1,引脚值与默认值DEFVAL比较。为0,引脚与先前值比较 0,与先前值比较
GPPU 输入时使用,配置相应的引脚上拉 1上拉使能,0不上拉 不上拉
INTF(flag) 反应了对应引脚(使能中断的引脚)的中断状态(只读) 1中断发生了,0中断没有发生 0
INTCAP 中断发生时捕获端口值(只读,只在中断发生时才会更新。在还没有读取寄存器的值时(或GPIO值),其值一直都保持不变) 1,逻辑高,0逻辑低
GPIO 可以读(获得端口值),写入该寄存器将修改输出锁存(OLAT)寄存器的值 1高
OLAT 输出锁存寄存器,读的话会读到OLAT,而不是端口 1高

配置寄存器IOCON
在这里插入图片描述

  • BANK(bit7):控制寄存器地址
  • MIRROR(bit6): 为1,任何一个端口上的中断都会使INTA和INTB激活。 为0,B端口中断使INTB激活,A端口中断INTA激活
  • SEQOP(bit5):连续操作模式位。 为1,禁止连续操作,地址指针不递增。 为0,使能连续操作,地址指针递增
  • DISSLW(bit4):不用他
  • HAEN(bit3):硬件地址使能位(1使用地址引脚配置地址)
  • ODR(bit2):开漏控制位,用于使能或禁止INT引脚的开漏输出,1使能
  • INTPOL(bit1):INT的输出极性,1高电平
  • bit0:保留

INTCON两种中断解释:

  • 默认值的时候,引脚只要与默认值不同则产生中断(可以设置为高电平中断,低电平中断)
  • 先前值,则当引脚值发生改变的时候就产生一次中断(电平变化中断)

在这里插入图片描述

代码

F407,HAL库代码

MCP23017.C


#include "MCP23017.h"

//--------------------------------------------------------------------------------------   
//  函数名称:bit MCP23017_INIT(unsigned char deviceAddr,unsigned char ab,unsigned char hwa,unsigned char o)
//  函数功能:初始化指定地址的MCP23017器件
//	参数:deviceAddr——设备地址,有A0,A1,A2决定
//		  intab——配置INTA、INTB是否关联,取值INTA_INTB_CONJUNCTION、INTA_INTB_INDEPENDENT
//		  hwa——配置A0、A1、A2硬件地址是否使能,取值HWA_EN、HWA_DIS	
//		  o——配置INTA、INTB的输出类型,取值INT_OD、INT_PUSHPULL_HIGH、INT_PUSHPULL_LOW 
//--------------------------------------------------------------------------------------   
HAL_StatusTypeDef MCP23017_INIT(uint16_t deviceAddr,unsigned char intab,unsigned char hwa,unsigned char o)
{
   
	unsigned char state;
	HAL_StatusTypeDef res;
	
	//首先设置其他位的默认状态
	state = 0x2E;		//001011 10,BANK = 0,默认不关联AB(bit = 0),禁用顺序操作,使能变化率控制、使能硬件地址,开漏输出
	if(intab==INTA_INTB_CONJUNCTION)
	{
   
		state |= 0x40;
	}
	if(hwa==HWA_DIS)
	{
   
		state &= (~0x08);
	}
	if(o==INT_PUSHPULL_HIGH)
	{
   
		state &= (~0x04);
		state |= 0x02;
	}
	if(o==INT_PUSHPULL_LOW)
	{
   
		state &= (~0x04);
		state &= (~0x02);
	}
	
	//写回方向寄存器
	res =HAL_I2C_Mem_Write(&hi2c1,deviceAddr,MCP23017_IOCON, I2C_MEMADD_SIZE_8BIT,&state, 1, 100);

	return res;
}
	

//--------------------------------------------------------------------------------------   
//  函数名称:MCP23017_IO_DIR(unsigned char deviceAddr,unsigned char port,unsigned char pin,unsigned char dir)
//  函数功能:设置制定地址的MCP23017的指定端口的指定引脚为输入或输出状态,其他引脚维持不变
//	参数:deviceAddr——设备地址,有A0,A1,A2决定
//		  port——端口名称,取值MCP23017_PORTA、MCP23017_PORTB
//		  pin——引脚号,取值PIN0-PIN7对应端口的8个引脚,ALLPIN包括端口所有8个引脚
//		  dir——输入输出方向,取值INPUT、OUTPUT 
//--------------------------------------------------------------------------------------   
HAL_StatusTypeDef MCP23017_IO_DIR(uint16_t deviceAddr,unsigned char port,unsigned char pin,unsigned char dir)
{
   
	unsigned char *portState;
	HAL_StatusTypeDef res;
	
	//首先读取当前端口方向的配置状态
	//因为B端口的地址比A端口的寄存器的地址都是大1,所以采用+的技巧切换寄存器
		res = HAL_I2C_Mem_Read(&hi2c1, deviceAddr, MCP23017_IODIR+port, I2C_MEMADD_SIZE_8BIT, portState, 1, 100);
		while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY)//需要加上这一段,不然会出错
	{
   
		
	}

	//如果出错则返回
	if(res != HAL_OK)
	{
   
		return res;
	}

	if(dir==INPUT)
	{
   
		*portState |= pin;
	}
	else
	{
   
		*portState &= (~pin);
	}

		//写回方向寄存器
	res =HAL_I2C_Mem_Write(&hi2c1,deviceAddr,MCP23017_IODIR+port, I2C_MEMADD_SIZE_8BIT,portState, 1, 100);
		while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY)
	{
   
		
	}
	return res;
}


//--------------------------------------------------------------------------------------   
//  函数名称:bit MCP23017_WRITE_GPIO(unsigned char deviceAddr,unsigned char port,unsigned char val)
//  函数功能:向指定地址的MCP23017的指定端口写值
//	参数:deviceAddr——设备地址,有A0,A1,A2决定
//		  port——端口名称,取值MCP23017_PORTA、MCP23017_PORTB
//		  val——要写入端口寄存器的值
//--------------------------------------------------------------------------------------   
HAL_StatusTypeDef 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

成草

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

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

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

打赏作者

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

抵扣说明:

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

余额充值