STM32的小打小闹(标准库)

        STM32是ST公司基于ARM Cortex-M内核开发的32位微控制器。这里以STM32C8T6为例子。通过标准库入门STM32的GPIO输入输出、EXTI外部中断、TIM定时器中断、TIM输出比较、TIM输入捕获、ADC数模转换、DMA、USART收发数据、I2C通讯、SPI通讯。根据b站江科大b站江科大视以及相关资料总结。这篇文章仅记录各种片上资源的使用流程,即标准库的使用。学习单片机基本知识的可以直接观看江科大的视频,讲得很详细。

一、STM32C8T6相关信息简介

1、基本信息

内核:ARM Cortex-M3

主频:72MHz RAM:20K(SRAM)

ROM:64K(Flash)

供电:2.0~3.6V(标准3.3V)

封装:LQFP48

2、片上外设资源

STM32的小打小闹(标准库)_第1张图片

3、系统结构

STM32的小打小闹(标准库)_第2张图片

 4、引脚定义

STM32的小打小闹(标准库)_第3张图片

 二、GPIO输入输出

使用GPIO输入输出需要使用相关库函数,配置结构体,指针进行初始化,往后的初始化也是如此,不了解结构体、指针的可以看这两篇文章C语言——结构体、C语言——指针。

//GPIO初始化
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//开启外设时钟	
GPIO_InitTypeDef GPIO_InitStructure;//定义GPIO初始化结构体变量
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP ;//设置GPIO模式
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0 ;//设置定义的GPIOk口
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//设置GPIO选中管脚的速率
GPIO_Init(GPIOA,&GPIO_InitStructure);//初始化GPIO

//常用函数
GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_SET);//设置或者清除指定的数据端口位
GPIO_ResetBits(GPIOA,GPIO_Pin_0);//端口置0
GPIO_SetBits(GPIOA,GPIO_Pin_0);//端口置1

GPIO模式 

STM32的小打小闹(标准库)_第4张图片

 外设GPIO配置STM32的小打小闹(标准库)_第5张图片

STM32的小打小闹(标准库)_第6张图片

STM32的小打小闹(标准库)_第7张图片 

 二、EXTI外部中断

EXTI和NVIC基本结构如下,通过配置GPIO、EXTI、NVIC可实现外部中断

STM32的小打小闹(标准库)_第8张图片

STM32的小打小闹(标准库)_第9张图片

//外部中断初始化
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//开启GPIOB和AFIO时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	
//根据GPIO_InitStruct参数配置GPIOx
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;//模式
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_14;//PIN口
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;//速度
GPIO_Init(GPIOB,&GPIO_InitStruct);//初始化
	
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource14);//选择 GPIO 管脚用作外部中断线路
	
//根据 EXTI_InitStruct 中指定的参数初始化外设 EXTI 寄存器
EXTI_InitTypeDef EXTI_InitStruct;
EXTI_InitStruct.EXTI_Line=EXTI_Line14;//外部中断线路
EXTI_InitStruct.EXTI_LineCmd=ENABLE;//使能
EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt;//设置为中断请求
EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Falling;//下降沿触发
EXTI_Init(&EXTI_InitStruct);
	
//中断优先级分组,只需要设置一次
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
//根据 NVIC_InitStruct 中指定的参数初始化外设 NVIC 寄存器
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel=EXTI15_10_IRQn;//用以使能或者失能指定的 IRQ 通道
NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;//使能
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级
NVIC_InitStruct.NVIC_IRQChannelSubPriority=1;//响应优先级
NVIC_Init(&NVIC_InitStruct);


//中断服务函数,若使用其他中断服务函数,可以去startup_stm32f10x_md.s文件查看中断服务函数名
void EXTI15_10_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line14)==SET)//判断中断标志位
	{
		CountSensor_Count++;
		
		EXTI_ClearITPendingBit(EXTI_Line14);//标志位清零
	}
}

 三、TIM定时中断

计数器计数频率:CK_CNT = CK_PSC / (PSC + 1)

计数器溢出频率:CK_CNT_OV = CK_CNT / (ARR + 1)= CK_PSC / (PSC + 1) / (ARR + 1) 

定时器基本结构

STM32的小打小闹(标准库)_第10张图片

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//使能外设时钟
	
TIM_InternalClockConfig(TIM2);//定时器使用内部时钟源
	
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//时基单元配置结构体
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//采样频率
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//计数方式
TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;//ARR自动重装器
TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;//PSC预分频器
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//定时器溢出再增加一个倍率rate 的控制,即两次溢出才会触发中断
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);//初始化TIM
	
TIM_ClearFlag(TIM2, TIM_FLAG_Update);//由于上电时会将TIM_FLAG_Update置1,会直接进入中断,所以需要在使能定时器前重新清零
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);//使能TIM中断
	
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级分组
	
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;//中断通道
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//响应优先级
NVIC_Init(&NVIC_InitStructure);
	
TIM_Cmd(TIM2, ENABLE);//使能时钟

void TIM2_IRQHandler(void)//定时器中断服务函数
{
	if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)//判断中断标志位
	{
		
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);//清除中断标志位
	}
}

四、TIM输出比较 

STM32的小打小闹(标准库)_第11张图片

STM32的小打小闹(标准库)_第12张图片

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//开启时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
//RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);//AFIO端口复用
//GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE);
//GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
	
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;		//GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO
	
TIM_InternalClockConfig(TIM2);//使用内部时钟源
	
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 100 - 1;		//ARR
TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1;		//PSC
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);//配置时基单元
	
TIM_OCInitTypeDef TIM_OCInitStructure;//输出比较结构体
TIM_OCStructInit(&TIM_OCInitStructure);//初始化结构体(结构体中有些参数是高级定时器的参数,基本不用用到,可以直接初始化)
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//PWM模式
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//输出极性
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//输出使能
TIM_OCInitStructure.TIM_Pulse = 0;		//CCR,与CNT值比较
TIM_OC1Init(TIM2, &TIM_OCInitStructure);//初始化
	
TIM_Cmd(TIM2, ENABLE);//使能TIM

五、TIM输入捕获

测频法:在闸门时间T内,对上升沿计次,得到N,则频率 f_x=N / T

测周法:两个上升沿内,以标准频率fc计次,得到N ,则频率 f_x=f_c / N

中界频率:测频法与测周法误差相等的频率点 f_m=√f_c / T

TIM输入捕获基本结构

STM32的小打小闹(标准库)_第13张图片

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO
	
TIM_InternalClockConfig(TIM3);//开启内部时钟
	
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1;		//ARR
TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;		//PSC
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);//初始化时基单元
	
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;//输入通道1
TIM_ICInitStructure.TIM_ICFilter = 0xF;//输入比较滤波器
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;//上升沿计数
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;//执行一次需要检测到的边沿个数
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//直连
TIM_ICInit(TIM3, &TIM_ICInitStructure);//初始化输入捕获通道
	
//TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);//使用PWMI模式,可以用于测量输入PEWM的占空比

TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);//选择输入触发源
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);//设置从模式,硬件清除CNT
	
TIM_Cmd(TIM3, ENABLE);//开启时钟

六、ADC数模转换

ADC基本结构

STM32的小打小闹(标准库)_第14张图片

RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
RCC_ADCCLKConfig(RCC_PCLK2_Div6);//ADC采样时钟
	
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO
	
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);//设置规则组
	
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//ADC模式
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//数据对齐
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//选择触发ADC通道
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//选择单次还是连续转换
ADC_InitStructure.ADC_ScanConvMode = DISABLE;//扫描模式
ADC_InitStructure.ADC_NbrOfChannel = 1;//规则组ADC通道数目
ADC_Init(ADC1, &ADC_InitStructure);//初始化ADC
	
ADC_Cmd(ADC1, ENABLE);//使能ADC

//ADC矫正
ADC_ResetCalibration(ADC1);
while (ADC_GetResetCalibrationStatus(ADC1) == SET);
ADC_StartCalibration(ADC1);
while (ADC_GetCalibrationStatus(ADC1) == SET);

七、DMA

DMA基本结构

STM32的小打小闹(标准库)_第15张图片

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
	
DMA_InitTypeDef DMA_InitStructure;
DMA_InitStructure.DMA_PeripheralBaseAddr = AddrA;//外设地址
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据宽度
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;//是否递增
DMA_InitStructure.DMA_MemoryBaseAddr = AddrB;//存储器地址
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//存储器数据宽度
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//是否自增
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//选择外设作为数据来源还是存储地址
DMA_InitStructure.DMA_BufferSize = Size;//DMA 缓存的大小
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//工作模式,循环还是单次
DMA_InitStructure.DMA_M2M = DMA_M2M_Enable;//选择软件触发还是硬件触发
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//优先级
DMA_Init(DMA1_Channel1, &DMA_InitStructure);//初始化DMA
	
DMA_Cmd(DMA1_Channel1, DISABLE);//使能DMA

//使用软件单次触发使用函数
void MyDMA_Transfer(void)
{
	DMA_Cmd(DMA1_Channel1, DISABLE);//停止DMA
	DMA_SetCurrDataCounter(DMA1_Channel1, MyDMA_Size);//设置DMA 缓存的大小,即搬运次数
	DMA_Cmd(DMA1_Channel1, ENABLE);//开启DMA
	
	while (DMA_GetFlagStatus(DMA1_FLAG_TC1) == RESET);//等待搬运
	DMA_ClearFlag(DMA1_FLAG_TC1);//清除标志位
}

八、USART

USART基本结构

STM32的小打小闹(标准库)_第16张图片

uint8_t Serial_RxData;//接收数据
uint8_t Serial_RxFlag;

void Serial_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);//开启外设时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);初始化GPIO
	
	USART_InitTypeDef USART_InitStructure;
	USART_InitStructure.USART_BaudRate = 9600;//设置波特率
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;指定硬件流控制模式使能还是失能
	USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;//发送接收均使能
	USART_InitStructure.USART_Parity = USART_Parity_No;//奇偶校验
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//停止位
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//数据位选择,8、9位
	USART_Init(USART1, &USART_InitStructure);//初始化USART
	
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//USART中断使能
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断分组
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);//中断初始化
	
	USART_Cmd(USART1, ENABLE);//USART使能
}
//发送一个字节
void Serial_SendByte(uint8_t Byte)
{
	USART_SendData(USART1, Byte);
	while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}
//发送一个数组
void Serial_SendArray(uint8_t *Array, uint16_t Length)
{
	uint16_t i;
	for (i = 0; i < Length; i ++)
	{
		Serial_SendByte(Array[i]);
	}
}
//发送字符串
void Serial_SendString(char *String)
{
	uint8_t i;
	for (i = 0; String[i] != '\0'; i ++)
	{
		Serial_SendByte(String[i]);
	}
}
//指数计算
uint32_t Serial_Pow(uint32_t X, uint32_t Y)
{
	uint32_t Result = 1;
	while (Y --)
	{
		Result *= X;
	}
	return Result;
}
//发送数字
void Serial_SendNumber(uint32_t Number, uint8_t Length)
{
	uint8_t i;
	for (i = 0; i < Length; i ++)
	{
		Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0');
	}
}
//
int fputc(int ch, FILE *f)
{
	Serial_SendByte(ch);
	return ch;
}
//
void Serial_Printf(char *format, ...)
{
	char String[100];
	va_list arg;
	va_start(arg, format);
	vsprintf(String, format, arg);
	va_end(arg);
	Serial_SendString(String);
}
//获取接收标志位
uint8_t Serial_GetRxFlag(void)
{
	if (Serial_RxFlag == 1)
	{
		Serial_RxFlag = 0;
		return 1;
	}
	return 0;
}
//接收数据
uint8_t Serial_GetRxData(void)
{
	return Serial_RxData;
}
//中断服务函数
void USART1_IRQHandler(void)
{
	if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)//判断标志位
	{
		Serial_RxData = USART_ReceiveData(USART1);
		Serial_RxFlag = 1;
		USART_ClearITPendingBit(USART1, USART_IT_RXNE);//清除标志位
	}
}

九、I2C通讯

1、软件I2C

void MyI2C_W_SCL(uint8_t BitValue)
{
	GPIO_WriteBit(GPIOB, GPIO_Pin_10, (BitAction)BitValue);
	Delay_us(10);
}

void MyI2C_W_SDA(uint8_t BitValue)
{
	GPIO_WriteBit(GPIOB, GPIO_Pin_11, (BitAction)BitValue);
	Delay_us(10);
}

uint8_t MyI2C_R_SDA(void)
{
	uint8_t BitValue;
	BitValue = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11);
	Delay_us(10);
	return BitValue;
}

void MyI2C_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	GPIO_SetBits(GPIOB, GPIO_Pin_10 | GPIO_Pin_11);
}

void MyI2C_Start(void)
{
	MyI2C_W_SDA(1);
	MyI2C_W_SCL(1);
	MyI2C_W_SDA(0);
	MyI2C_W_SCL(0);
}

void MyI2C_Stop(void)
{
	MyI2C_W_SDA(0);
	MyI2C_W_SCL(1);
	MyI2C_W_SDA(1);
}

void MyI2C_SendByte(uint8_t Byte)
{
	uint8_t i;
	for (i = 0; i < 8; i ++)
	{
		MyI2C_W_SDA(Byte & (0x80 >> i));
		MyI2C_W_SCL(1);
		MyI2C_W_SCL(0);
	}
}

uint8_t MyI2C_ReceiveByte(void)
{
	uint8_t i, Byte = 0x00;
	MyI2C_W_SDA(1);
	for (i = 0; i < 8; i ++)
	{
		MyI2C_W_SCL(1);
		if (MyI2C_R_SDA() == 1){Byte |= (0x80 >> i);}
		MyI2C_W_SCL(0);
	}
	return Byte;
}

void MyI2C_SendAck(uint8_t AckBit)
{
	MyI2C_W_SDA(AckBit);
	MyI2C_W_SCL(1);
	MyI2C_W_SCL(0);
}

uint8_t MyI2C_ReceiveAck(void)
{
	uint8_t AckBit;
	MyI2C_W_SDA(1);
	MyI2C_W_SCL(1);
	AckBit = MyI2C_R_SDA();
	MyI2C_W_SCL(0);
	return AckBit;
}

2、硬件I2C

RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;//开漏复用输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO
	
I2C_InitTypeDef I2C_InitStructure;
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;//模式
I2C_InitStructure.I2C_ClockSpeed = 50000;//时钟速度
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;//占空比
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;//应答使能
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;//自身地址位数
I2C_InitStructure.I2C_OwnAddress1 = 0x00;//地址
I2C_Init(I2C2, &I2C_InitStructure);//初始化I2C
	
I2C_Cmd(I2C2, ENABLE);

STM32的小打小闹(标准库)_第17张图片

STM32的小打小闹(标准库)_第18张图片

根据接收传送序列图,使用如下函数,实现I2C读写字节

I2C_GenerateSTART(I2C2, ENABLE);//传输开始
I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Transmitter);//发送地址
I2C_SendData(I2C2, RegAddress);//发送数据
I2C_GenerateSTOP(I2C2, ENABLE);//传输结束
I2C_AcknowledgeConfig(I2C2, DISABLE);//使能使能应答
I2C_ReceiveData(I2C2);//接收数据
I2C_CheckEvent(I2Cx, I2C_EVENT);//判断标志位

你可能感兴趣的:(STM32的小打小闹,stm32,单片机,嵌入式硬件,c语言)