stm32软件i2c

硬件i2c,,并不是非用不可,,, 硬件i2c需要占用引脚

c 复制代码
#include "stm32f10x.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "buzzer.h"
#include "lightSensor.h"
#include "stdio.h"

// 用 PA0 和 PA1 
void my_softI2c_init(){

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	GPIO_InitTypeDef GPIO_initStruct = {0};
	
	// 操控引脚 
	GPIO_initStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
	
	// 开漏输出
	GPIO_initStruct.GPIO_Mode = GPIO_Mode_Out_OD;
	GPIO_initStruct.GPIO_Speed = GPIO_Speed_50MHz;
	
	// 初始化IO引脚,,
	GPIO_Init(GPIOA,&GPIO_initStruct);
	

}
/**
向 scl 写 0 或者写1
*/
void scl_write(uint8_t level){
	GPIO_WriteBit(GPIOA,GPIO_Pin_0,(BitAction)level);
}


void sda_write(uint8_t level){
	GPIO_WriteBit(GPIOA,GPIO_Pin_1,(BitAction)level);
}

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

/**

72MHz
*/
void delay_us(uint32_t us){
	
	uint32_t n = us*8;
	for(uint32_t i = 0;i<n;i++);
}

/**
发送起始位
*/
void sendStart(void){
	sda_write(0);
	delay_us(1);
}

/**
发送停止位
*/
void sendStop(void){
	// 确保在 scl为低电平的时候,,去修改 sda
	
	scl_write(0);
	sda_write(0);
	Delay(1);
	
	scl_write(1);
	Delay(1);
	
	sda_write(1);
	Delay(1);
}


uint8_t sendByte(uint8_t byte){
	
	for(int8_t i=0;i<8;i++){
		// 拉低准备数据
		scl_write(0);
		
		if((byte & (0x80 >> i))!=0){
			sda_write(1);
		}else{
			sda_write(0);
		}
		
		delay_us(1);
		scl_write(1);
		delay_us(1);
	}
	
	
	
	scl_write(0);
	// 释放sda线,, 让别人回复
	sda_write(1);
	delay_us(1);
	
	
	scl_write(1);
	delay_us(1);
	// 读取nack 或者ack
	return sda_read();
}



uint8_t receiveByte(uint8_t ackFlag){

	uint8_t byte = 0x00;
	
	for(int8_t i=0;i<8;i++){
		scl_write(0);
		// 释放sda线,, 让别人发数据
		sda_write(1);
		
		delay_us(1);
		scl_write(1);
		delay_us(1);
		// 读取sda
		
		if(sda_read() == 1){
			byte = byte | (0x80 >> i);
		}
		
		
	}
	
	
	// 发送ack
	scl_write(0);
	

	sda_write(ackFlag);
	
	
	delay_us(1);
	scl_write(1);
		
	delay_us(1);
		
	
	return byte;
}



	
	






/**
板载led初始化
*/
void my_onBoardLED_init(){
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
	GPIO_InitTypeDef GPIO_initStruct = {0};
	
	// 操控引脚 
	GPIO_initStruct.GPIO_Pin = GPIO_Pin_13;
	
	// 板载led ,,是开漏输出
	GPIO_initStruct.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_initStruct.GPIO_Speed = GPIO_Speed_50MHz;
	
	// 初始化IO引脚,,
	GPIO_Init(GPIOC,&GPIO_initStruct);
	
	
	GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET);
}


void my_oled_init(){
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	GPIO_InitTypeDef GPIO_initStruct = {0};
	
	// 操控引脚 
	GPIO_initStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
	

	// 必须是开漏,,多设备共用一根线,,如果多个人输出高,,就短路了,,I2C规定只能拉低
	GPIO_initStruct.GPIO_Mode = GPIO_Mode_AF_OD;
	GPIO_initStruct.GPIO_Speed = GPIO_Speed_50MHz;
	
	// 初始化IO引脚,,
	GPIO_Init(GPIOB,&GPIO_initStruct);
	
	
	
	
	
		// 开时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);
	
	// 开启复位信号
	RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1,ENABLE);
	
	// 关闭复位信号  ,,, 硬件的复位本质上是一个脉冲
	RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1,DISABLE);
	
	
	
	I2C_InitTypeDef i2c_initStruct;
	
	i2c_initStruct.I2C_ClockSpeed = 400000;
	
	i2c_initStruct.I2C_Mode = I2C_Mode_I2C;
	
	i2c_initStruct.I2C_DutyCycle = I2C_DutyCycle_2;
	
	I2C_Init(I2C1,&i2c_initStruct);
	
	
	// 闭合I2C1的总开关
	I2C_Cmd(I2C1,ENABLE);

}



/**
接收从机数据
*/
int my_softI2c_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;i++){
		
		if(i==size-1){
			pBuffer[i] = receiveByte(0);
		}else{
			pBuffer[i] = receiveByte(1);
		}
		
	
	}
	
	
	sendStop();
	
	
	
	return 0;
	
	

}
/**
addr : 地址
pBuffer: 要发送的数据
size : 要发送数据的数量
*/
int my_softI2c_sendBytes(uint8_t addr,uint8_t *pData,uint16_t size){
	
	sendStart();
	// 写数据,最后一位是0
	if(sendByte(addr & 0xfe ) != 0){
		// 寻址不成功
		sendStop();
		return -1;
	}
	
	for(uint32_t i=0;i<size;i++){
		if(sendByte(pData[i]) != 0){
			// 没有ack,,数据被拒收
				sendStop();
				return -2; 
		}
		
	}
	
	
	
		sendStop();
		return 0;
	
}


int main(void)
{
	

	// 初始化 PA0 和 PA1
	my_softI2c_init();
	

//	uint8_t commands[] = {0x00,0x8d,0x14,0xaf,0xa5};
//	
//	my_softI2c_sendBytes(0x78,commands,5);
//	
	while(1)
	{
		

	}
}
相关推荐
俊基科技9 小时前
A-59U工业级多模语音处理模块在矿山矿井通信与呼叫报警系统中的应用
嵌入式硬件·嵌入式开发·硬件开发·ai降噪·回音消除·拾音降噪
周周记笔记10 小时前
GD32F450xx MCU Datasheet 解读:硬件测试工程师的测试方法论
单片机·嵌入式硬件
潘潘的嵌入式日记12 小时前
I²C 从机接收总被覆盖?双缓冲要在 STOP 时交接
c语言·开发语言·单片机
AOI小白新手上路14 小时前
江科协51单片机16-1 AD/DA ADC 三通道综合显示(LCD1602 版)改造说明
单片机·嵌入式硬件·51单片机
HUI-47414 小时前
EG1135|SSOP‑16 同步整流降压控制器,大功率外置 MOS 降压优选
单片机·嵌入式硬件·硬件工程
单片机仿真设计15 小时前
【proteus仿真】基于 STM32 单片机恒温箱控制系统设计(仿真图+程序)
stm32·单片机·嵌入式硬件·proteus·毕设
国科安芯15 小时前
星载CAN总线通信网络中抗辐射MCU的通信可靠性设计分析
网络·人工智能·分布式·单片机·嵌入式硬件·架构
新晨单片机设计17 小时前
S003A-基于STM32单片机温度计(数码管显示)【Proteus仿真+Keil程序+原理图】
stm32·单片机·stm32单片机功能定制
一条破秋裤17 小时前
TIM 输入捕获与 PWMI:从边沿到频率、占空比
笔记·stm32·学习
AOI小白新手上路17 小时前
江科协51单片机16-1 DA数模转换实验(PWM 呼吸灯)
单片机·嵌入式硬件·51单片机