STM32学习-19-[I2C]软I2C

IO引脚的初始化

使用普通引脚模拟I2C结构,这里使用PA0和PA1
先对其进行初始化

void My_SI2C_Init(void){
	RCC_APB1PeriphCLockCmd(RCC_APB2Periph_GPIOA, ENABLE);

	GPIO_InitTypeDef GPIO_InitStruct;

	GPIO_InitStruct.GPIO_Pin = 	GPIO_Pin_0 | GPIO_Pin_1;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;

	GPIO_Init(GPIOA, &GPIO_InitStruct);
	
	// 记得设置高电压
	GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
	GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_SET);
}

IO读写和延迟函数

image

void scl_weite(uint8_t level){
	// PA0
	if(level == 0){
		GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET);
	}
	else{
		GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
	}
}

void sda_weite(uint8_t level){
	// PA1
	if(level == 0){
		GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_RESET);
	}
	else{
		GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_SET);
	}
}

uint8_t sda_read(void){
	if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1) == Bit_SET){
		return 1;
	}
	else{
		return 0;
	}
}

void delay_us(uint32_t us){
	uint32_t n = us * 8;
	for(uint32_t i = n; i >= 0; --i);
}

发送起始位和停止位

image

void SendStart(void){
	sda_write(0);
	delay_us(1);
}

void SendStop(void){
	scl_write(0);
	sda_write(0);
	delay_us(1);
	scl_write(1);
	delay_us(1);
	sda_write(1);
	delay_us(1);
}

发送一字节数据

image

image

uint8_t SendByte(uint8_t Byte){
	// 先发高位
	for(int8_t i = 7; i >= 0; --i){
		scl_write(0);

		if((Byte & (0x01 << i)) != 0){
			sda_write(1);
		}
		else{
			sda_write(0);
		}

		sda_write(x);
		delay_us(1);
		scl_write(1);
		delay_us(1);
	}

	// 读取ACK或者NAK
	scl_write(0);
	sda_write(1);
	delay_us(1);
	scl_write(1);
	delay_us(1);
	return sda_read();
}

接收一个字节

image

image

uint8_t ReveiveByte(uint8_t Ack){
	uint8_t byte = 0;
	// 从高到底的读
	for(int8_t i = 7; i >= 0; --i){
		scl_write(0);
		sda_write(1);
		delay_us(1);
		scl_write(1);
		delay_us(1);
		if(sda_read() != 0){
			byte |= (0x01 << i);
		}
	}

	// 回复ACK或NAK
	scl_write(0);
	sda_write(!Ack);
	delay_us(1);
	scl_write(1);
	delay_us(1);
	return byte;
}

综合

image

int My_SI2C_SendBytes(uint8_t Addr, uint8_t *pData, uint16_t Size){
	// 寻址
	SendStart();
	if(SendByte(Addr & 0xfe) != 0){
		SendStop();
		return -1;
	}

	// 发送数据
	for(uint32_t i = 0; i < Size; ++i){
		if(SendByte(pData[i]) != 0){
			SendStop();
			return -2;
		}
	}

	SendStop();
}

int My_SI2C_ReceiveBytes(uint8_t Addr, uint8_t *pBuffer, uint16_t Size){
	SendStart();
	if(SendByte(Addr | 0x01) != 0){
		SendStop();
		return -1;
	}

	for(uint32_t i = 0; i < Size - 1; ++i){
		pBuffer[i] = ReceiveByte(1);
	}

	pBuffer[Size - 1] = ReceiveByte(0);
	
	SendStop();
}
posted @ 2026-09-01 10:38  灵垚克府  阅读(6)  评论(0)    收藏  举报