stm,铁头山羊代码

该文章已生成可运行项目,

 led长端接阳极,按钮看底部连线

#include "stm32f10x.h"
#include"delay.h"
int main(void)
{
	//定时器
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//STM32 的外设(如 GPIO)默认处于时钟关闭状态,
	//使用前必须先使能对应时钟。GPIOC 挂载在 APB2 总线上,因此使用RCC_APB2PeriphClockCmd()函数。
	
	GPIO_InitTypeDef GPIO_InitStruct={0};//一个内置结构体
	
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_13;//引脚
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_OD;//输出模式
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_2MHz;//输出速度
	
	GPIO_Init(GPIOC,&GPIO_InitStruct);//将配置参数应用到 GPIOC 端口。
	
	while(1)
	{
		GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_RESET);//1.模块,2.引脚,3.点亮(通用输出开漏
		Delay(100);
		GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET);
		Delay(100);
	}
}

设置系统板上绿灯闪烁 

输入输出mode
GPIO_Mode_Out_PP通用输出推挽,push pull
GPIO_Mode_Out_OD通用输出开漏,open drain
GPIO_Mode_AF_pp复用输出推挽,AF=Alternate Function
GPIO_Mode_AF_OD复用输出开漏
GPIO_Mode_IPU输入上拉,Input pull up
GPIO_Mode_IPD输入下拉Input pull down
GPIO_Mode_IN_FLOATING输入浮空
GPIO_Mode_AIN模拟模式 Analog Input

按钮点灯

#include "stm32f10x.h"
#include"delay.h"
int main(void)
{
	//定时器
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStruct={0};
	
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_2MHz;
	
	GPIO_Init(GPIOA,&GPIO_InitStruct);//连接灯的部分
	
	//GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_SET);
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_1;
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;
	GPIO_Init(GPIOA,&GPIO_InitStruct);//按钮的部分
	
	while(1)
	{//输入上拉,即按钮按下后输入比特为0:RESET
		if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_1)==Bit_RESET){
			GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_SET);//给灯写入1:Bit_SET
	}else{
		GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_RESET);
	}
}
}

串口初始化

#include "stm32f10x.h"
#include"delay.h"
int main(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//是使能 USART1 的时钟
    
    //开启通信接口
    USART_Cmd(USART1,ENABLE);

    //创建了一个USART_InitTypeDef类型的结构体变量USART_Struct,并对其进行初始化
	USART_InitTypeDef USART_Struct;
	USART_Struct.USART_BaudRate=115200;
	USART_Struct.USART_Mode=USART_Mode_Rx | USART_Mode_Tx;
	USART_Struct.USART_WordLength=USART_WordLength_8b;
	USART_Struct.USART_StopBits=USART_StopBits_1;
	USART_Struct.USART_Parity=USART_Parity_No;
	//该函数会按照USART_Struct结构体中的参数配置,对 USART1 进行初始化。
	USART_Init(USART1,&USART_Struct);
	
	while(1)
	{
		
	}
}

为串口初始化IO引脚(USART1

txPA9
rxPA10
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	GPIO_InitTypeDef GPIO_InitStruct;
	//PA9,tx
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_10MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	//PA10 rx
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	//重映射,重映射后引脚更换:PB6:tx       PB7:rx
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	GPIO_PinRemapConfig(GPIO_Remap_USART1,ENABLE);
//后面与之前设置引脚方式相同,GPIOA换为GPIOB,
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	GPIO_InitTypeDef GPIOin;
	GPIOin.GPIO_Pin=GPIO_Pin_6;//PB6  tx
	GPIOin.GPIO_Mode=GPIO_Mode_AF_PP;
	GPIOin.GPIO_Speed=GPIO_Speed_10MHz;
	GPIO_Init(GPIOB,&GPIOin);
	
	GPIOin.GPIO_Mode=GPIO_Mode_IPU;
	GPIOin.GPIO_Pin=GPIO_Pin_7;//PB7  rx
	GPIO_Init(GPIOB,&GPIOin);
	

自定义数据发送函数

void My_USART_SendBytes(USART_TypeDef *USARTx,uint8_t *pData,uint16_t Size){
		
	for(uint32_t i=0;i<Size;i++){
		//等待发送数据寄存器为 空
		while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
		//写入发数据寄存器中
		USART_SendData(USARTx,pData[i]);
	}
	//等待发送全部完成
	while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
}
	
//重载内置函数,可以使用printf在串口调试助手收到数据
int fputc(int ch,FILE *f)
{
	//等待发送数据寄存器为 空
	while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
	//一个字节一个字节发送
	USART_SendData(USART1,(uint8_t)ch);
	return ch;
}
USART引脚配置GPIO配置
USARTx_TX全双工模式推挽复用输出
半双工同步模式推挽复用输出
USARTx_Rx全双工模式浮空输入或上拉输入(最好上拉输入
半双工同步模式未用

I2C引脚

复用功能I2C1_REMAP=0I2C_REMAP=1
I2C1I2C1_SCLPB6PB8
I2C1_SDAPB7PB9
I2C2I2C2_SCL无重映射PB10
I2C2_SDAPB11

I2Cx_SCL:I2C时钟,开漏复用输出

I2Cx_SDA:I2C数据,开漏复用输出

void My_I2C_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	GPIO_PinRemapConfig(GPIO_Remap_I2C1,ENABLE);//重映射
	
	//对PB8|9初始化
	GPIO_InitTypeDef in;
	in.GPIO_Mode=GPIO_Mode_AF_OD;
	in.GPIO_Pin=GPIO_Pin_8|GPIO_Pin_9;
	in.GPIO_Speed=GPIO_Speed_2MHz;
	GPIO_Init(GPIOB,&in);
	
	//初始化I2C
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);
	
	RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1,ENABLE);//施加复位信号
	RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1,DISABLE);//释放复位信号
	
	I2C_InitTypeDef I2c_Struct;
	I2c_Struct.I2C_ClockSpeed=400000;//设置速度
	I2c_Struct.I2C_DutyCycle=I2C_DutyCycle_2;//设置2:1的占空比
	I2c_Struct.I2C_Mode=I2C_Mode_I2C;//标准模式
	I2C_Init(I2C1,&I2c_Struct);
	
	I2C_Cmd(I2C1,ENABLE);//闭合总开关
	

}

I2C发送字节(未成功

int My_I2C_SendBytes(I2C_TypeDef *I2Cx,uint8_t addr,uint8_t *pData,uint16_t Size)
{
	//1.等待总线空闲
	while(I2C_GetFlagStatus(I2Cx,I2C_FLAG_BUSY)==SET);//BUSY:总线标志位,0:空闲;1:忙
	//2.发送起始位
	I2C_GenerateSTART(I2Cx,ENABLE);//发送起始位
	while(I2C_GetFlagStatus(I2Cx,I2C_FLAG_SB)==RESET);//SB:起始位发送状态;0:未发送;1:发送完成
	//3.寻址阶段
	I2C_ClearFlag(I2Cx,I2C_FLAG_AF);//清除AF标志位,AF:应答失败,1:未收到ACK
	I2C_SendData(I2Cx,addr & 0xfe);//发送地址+RW#
	while(1){
		if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_ADDR)==SET)break;//ADDR:寻址成功;
		if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_AF)==SET){
			I2C_GenerateSTOP(I2Cx,ENABLE);//发送停止位并返回-1,寻址失败
			return -1;
		}
	}
	//清除ADDR
	I2C_ReadRegister(I2Cx,I2C_Register_SR1);
	I2C_ReadRegister(I2Cx,I2C_Register_SR2);
	//4.发送数据
	for(uint16_t i=0;i<Size;i++){
		while(1){
			if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_AF)==SET){
				I2C_GenerateSTOP(I2Cx,ENABLE);
				return -2;//数据被拒收
			}
			if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_TXE)==SET)break;
		}
		I2C_SendData(I2Cx,pData[i]);
	}
	
	while(1)
	{
		if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_AF)==SET){
			I2C_GenerateSTOP(I2Cx,ENABLE);
			return -2;
		}
		if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_BTF)==SET){
			break;
		}
	}
	I2C_GenerateSTOP(I2Cx,ENABLE);
	return 0;
	
}

按4.4,点亮显示屏,但未亮。

int main(void)
{
	My_I2C_Init();
	
	uint8_t c[]={0x00,0x8d,0x14,0xaf,0xa5};
	My_I2C_SendBytes(I2C1,0x78,c,5);

	
	
	while(1)
	{
		
	}
}

I2C接收数据

int My_I2CReceiveBytes(I2C_TypeDef*I2Cx,uint8_t Addr,uint8_t*pBuffer,uint16_t Size)
{
	//1.发送起始位
	I2C_GenerateSTART(I2Cx,ENABLE);
	while(I2C_GetFlagStatus(I2Cx,I2C_FLAG_SB)==RESET);
	//2.寻址阶段
	I2C_ClearFlag(I2Cx,I2C_FLAG_AF);
	I2C_SendData(I2Cx,Addr|0x01);
	while(1){
		if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_AF)==SET){
			I2C_GenerateSTOP(I2Cx,ENABLE);
			return -1;//寻址失败
		}
		if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_ADDR)==SET)
		{break;}
	}
	//3.接收数据
	if(Size==1){
		//清除ADDR
		I2C_ReadRegister(I2Cx,I2C_Register_SR1);
		I2C_ReadRegister(I2Cx,I2C_Register_SR2);
		//ACK=0,STOP=1
		I2C_AcknowledgeConfig(I2Cx,DISABLE);
		I2C_GenerateSTOP(I2Cx,ENABLE);
		//RxNE->1
		while(I2C_GetFlagStatus(I2Cx,I2C_FLAG_RXNE)==RESET);
		//读取数据
		pBuffer[0]=I2C_ReceiveData(I2Cx);
		
	}else if(Size==2){
		//清除ADDR标志位
		I2C_ReadRegister(I2Cx,I2C_Register_SR1);
		I2C_ReadRegister(I2Cx,I2C_Register_SR2);
		//ACK=1
		I2C_AcknowledgeConfig(I2Cx,ENABLE);
		//等待接收完成
		while(I2C_GetFlagStatus(I2Cx,I2C_FLAG_RXNE)==RESET);
		//读取第一个字节
		pBuffer[0]=I2C_ReceiveData(I2Cx);
		//ACK=0,STOP=1
		I2C_AcknowledgeConfig(I2Cx,DISABLE);
		I2C_GenerateSTOP(I2Cx,ENABLE);
		//等待接收完成
		while(I2C_GetFlagStatus(I2Cx,I2C_FLAG_RXNE)==RESET);
		pBuffer[1]=I2C_ReceiveData(I2Cx);
	}else{//size>2
		//清除ADDR标志位
		I2C_ReadRegister(I2Cx,I2C_Register_SR1);
		I2C_ReadRegister(I2Cx,I2C_Register_SR2);
		//ACK=1
		I2C_AcknowledgeConfig(I2Cx,ENABLE);
		for(uint16_t i=0;i<Size-1;i++){
				//等待接收完成
				while(I2C_GetFlagStatus(I2Cx,I2C_FLAG_RXNE)==RESET);
				//读取数据
				pBuffer[i]=I2C_ReceiveData(I2Cx);
		}
			//ACK=0,STOP=1
		I2C_AcknowledgeConfig(I2Cx,DISABLE);
		I2C_GenerateSTOP(I2Cx,ENABLE);
		//等待接收完成
		while(I2C_GetFlagStatus(I2Cx,I2C_FLAG_RXNE)==RESET);
		pBuffer[Size-1]=I2C_ReceiveData(I2Cx);
	}
	return 0;
	
}

使用代码:当显示屏亮起,板载led亮

int main(void)
{
	My_I2C_Init();
	My_boardLED_Init();
	uint8_t c[]={0x00,0x8d,0x14,0xaf,0xa5};
	My_I2C_SendBytes(I2C1,0x78,c,5);
	uint8_t rcvd;
	My_I2CReceiveBytes(I2C1,0x78,&rcvd,1);
	if((rcvd&(0x01<<6))==0){
		GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_RESET);
	}else{
		GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET);
	}
	
	while(1)
	{
		
	}
}

按钮点灯高级版

int main(void)
{
	button();
	My_boardLED_Init();
	uint8_t pre=Bit_SET,cur=Bit_SET;
	uint8_t isan=0;
	while(1)
	{
		cur=GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_8);
		if(pre!=cur){
			isan=1;
			Delay(10);//防抖
		}
		if(isan==1&&pre==cur){
			isan=0;
			if(GPIO_ReadOutputDataBit(GPIOC,GPIO_Pin_13)==Bit_RESET){
				GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET);
			}else{
				GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_RESET);
			}
			Delay(10);
		}
	}
}
void My_boardLED_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
	GPIO_InitTypeDef in;
	in.GPIO_Mode=GPIO_Mode_Out_OD;
	in.GPIO_Pin=GPIO_Pin_13;
	in.GPIO_Speed=GPIO_Speed_2MHz;
	GPIO_Init(GPIOC,&in);
	GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_RESET);//默认点亮
}
void button(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	GPIO_InitTypeDef in;
	in.GPIO_Mode=GPIO_Mode_IPU;
	in.GPIO_Pin=GPIO_Pin_8;
	in.GPIO_Speed=GPIO_Speed_2MHz;
	GPIO_Init(GPIOB,&in);
}
SPI1引脚
复用功能SPI1_REMAP=0...=1
SPI1_NSSPA4PA15
SPI1_SCKPA5PB3
SPI1_MISOPA6PB4
SPI1_MOSIPA7PB5

spi初始化1

RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE);
SPI_InitTypeDef spi;
spi.SPI_Mode=SPI_Mode_Master;                // 配置为主机模式
spi.SPI_Direction=SPI_Direction_2Lines_FullDuplex;  // 双线全双工模式
spi.SPI_DataSize=SPI_DataSize_8b;            // 数据宽度为8位
spi.SPI_CPOL=SPI_CPOL_High;                  // 时钟极性:空闲时为高电平
spi.SPI_CPHA=SPI_CPHA_2Edge;                 // 时钟相位:第二个边沿采样
spi.SPI_FirstBit=SPI_FirstBit_MSB;           // 高位在前
spi.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_64;  // 波特率分频:64分频
spi.SPI_NSS=SPI_NSS_Soft;                    // 软件控制片选
SPI_Init(SPI1,&spi);
SPI_NSSInternalSoftwareConfig(SPI1,SPI_NSSInternalSoft_Set);  // 内部NSS信号设置为高

使用w25q64模块保存数据

#include "stm32f10x.h" // 确保包含正确的头文件
#include<stdio.h>
#include"button.h"

void SPI1_init(void);
void spi_masttrans(SPI_TypeDef* SPIx, const uint8_t *pDataTx, uint8_t *pDataRx, uint16_t Size);
void savew25bits(uint8_t byte);
uint8_t loadw25bits(void);
void My_boardLED_Init(void);
Button_TypeDef button;
void button_in(void);
void but_cb(uint8_t click);


int main(void)
{
    SPI1_init();
		My_boardLED_Init();
		button_in();
    uint8_t b=loadw25bits();
		if(b==1){
			GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET);
		}else if(b==0){
			GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_RESET);
		}
    while(1)
    {
			My_Button_Proc(&button);
    }
}

void but_cb(uint8_t click)
{
	if(click==1){
		if(GPIO_ReadOutputDataBit(GPIOC,GPIO_Pin_13)==Bit_RESET){
			GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET);
			savew25bits(0x01);
		}else{
			GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_RESET);
			savew25bits(0x00);
		}
		
	}
}
void button_in(void)
{
	Button_InitTypeDef bu={0};
	bu.GPIOx=GPIOA;
	bu.GPIO_Pin=GPIO_Pin_0;
	bu.button_clicked_cb=but_cb;
	My_Button_Init(&button,&bu);
}
void My_boardLED_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
	GPIO_InitTypeDef in;
	in.GPIO_Mode=GPIO_Mode_Out_OD;
	in.GPIO_Pin=GPIO_Pin_13;
	in.GPIO_Speed=GPIO_Speed_2MHz;
	GPIO_Init(GPIOC,&in);

}
void SPI1_init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    GPIO_PinRemapConfig(GPIO_Remap_SPI1, ENABLE);
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    GPIO_InitTypeDef in;
    in.GPIO_Mode = GPIO_Mode_AF_PP;
    in.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_5;
    in.GPIO_Speed = GPIO_Speed_50MHz; // SPI通常需要更高速度
    GPIO_Init(GPIOB, &in); // PB3 SCK, PB5 MOSI
    
    in.GPIO_Mode = GPIO_Mode_IPU;
    in.GPIO_Pin = GPIO_Pin_4;
    GPIO_Init(GPIOB, &in); // PB4 MISO
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    in.GPIO_Mode = GPIO_Mode_Out_PP;
    in.GPIO_Pin = GPIO_Pin_15;
    in.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &in); // PA15 片选
    GPIO_WriteBit(GPIOA, GPIO_Pin_15, Bit_SET); // 默认拉高片选
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
    SPI_InitTypeDef spi;
    spi.SPI_Mode = SPI_Mode_Master;
    spi.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    spi.SPI_DataSize = SPI_DataSize_8b;
    spi.SPI_CPOL = SPI_CPOL_Low;
    spi.SPI_CPHA = SPI_CPHA_1Edge;
    spi.SPI_FirstBit = SPI_FirstBit_MSB;
    spi.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; // 适当提高速度
    spi.SPI_NSS = SPI_NSS_Soft;
    spi.SPI_CRCPolynomial = 7; // 必须初始化的参数
    SPI_Init(SPI1, &spi);
    SPI_Cmd(SPI1, ENABLE); // 初始化时就使能SPI
}

// 修正函数名拼写和传输逻辑
void spi_masttrans(SPI_TypeDef* SPIx, const uint8_t *pDataTx, uint8_t *pDataRx, uint16_t Size)
{
    for(uint16_t i = 0; i < Size; i++)
    {
        // 等待发送缓冲区为空
        while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET);
        SPI_I2S_SendData(SPIx, pDataTx[i]);
        
        // 等待接收缓冲区有数据
        while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET);
        if(pDataRx != NULL) // 确保接收缓冲区有效
        {
            pDataRx[i] = SPI_I2S_ReceiveData(SPIx);
        }
        else
        {
            // 不需要接收时仍需读取数据清除标志
            SPI_I2S_ReceiveData(SPIx);
        }
    }
    // 等待传输完成
    while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_BSY) == SET);
}

void savew25bits(uint8_t byte)
{
    uint8_t buffer[10];
    
    // 1. 写使能
    buffer[0] = 0x06;
    GPIO_WriteBit(GPIOA, GPIO_Pin_15, Bit_RESET); // 拉低片选
    spi_masttrans(SPI1, buffer, NULL, 1);
    GPIO_WriteBit(GPIOA, GPIO_Pin_15, Bit_SET); // 拉高片选
    
    // 2. 扇区擦除
    buffer[0] = 0x20; // 扇区擦除命令
    buffer[1] = 0x00; // 地址高位
    buffer[2] = 0x00; // 地址中位
    buffer[3] = 0x00; // 地址低位
    GPIO_WriteBit(GPIOA, GPIO_Pin_15, Bit_RESET);
    spi_masttrans(SPI1, buffer, NULL, 4);
    GPIO_WriteBit(GPIOA, GPIO_Pin_15, Bit_SET);
    
    // 3. 等待擦除完成
    while(1)
    {
        GPIO_WriteBit(GPIOA, GPIO_Pin_15, Bit_RESET);
        buffer[0] = 0x05; // 读状态寄存器命令
        spi_masttrans(SPI1, buffer, buffer, 1);
        // 发送一个空字节以读取状态
        spi_masttrans(SPI1, buffer, buffer, 1);
        GPIO_WriteBit(GPIOA, GPIO_Pin_15, Bit_SET);
        
        if((buffer[0] & 0x01) == 0) // 检查忙标志
            break;
    }
    
    // 4. 再次写使能(擦除后需要重新使能)
    buffer[0] = 0x06;
    GPIO_WriteBit(GPIOA, GPIO_Pin_15, Bit_RESET);
    spi_masttrans(SPI1, buffer, NULL, 1);
    GPIO_WriteBit(GPIOA, GPIO_Pin_15, Bit_SET);
    
    // 5. 页编程
    buffer[0] = 0x02; // 页编程命令
    buffer[1] = 0x00; // 地址高位
    buffer[2] = 0x00; // 地址中位
    buffer[3] = 0x00; // 地址低位
    buffer[4] = byte; // 要写入的数据
    GPIO_WriteBit(GPIOA, GPIO_Pin_15, Bit_RESET);
    spi_masttrans(SPI1, buffer, NULL, 5);
    GPIO_WriteBit(GPIOA, GPIO_Pin_15, Bit_SET);
    
    // 6. 等待编程完成
    while(1)
    {
        GPIO_WriteBit(GPIOA, GPIO_Pin_15, Bit_RESET);
        buffer[0] = 0x05; // 读状态寄存器命令
        spi_masttrans(SPI1, buffer, buffer, 1);
        spi_masttrans(SPI1, buffer, buffer, 1);
        GPIO_WriteBit(GPIOA, GPIO_Pin_15, Bit_SET);
        
        if((buffer[0] & 0x01) == 0) // 检查忙标志
            break;
    }
}

uint8_t loadw25bits(void)
{
    uint8_t buffer[10] = {0};
    
    // 读取数据命令和地址
    buffer[0] = 0x03; // 读数据命令
    buffer[1] = 0x00; // 地址高位
    buffer[2] = 0x00; // 地址中位
    buffer[3] = 0x00; // 地址低位
    
    GPIO_WriteBit(GPIOA, GPIO_Pin_15, Bit_RESET);
    // 发送命令和地址
    spi_masttrans(SPI1, buffer, NULL, 4);
    // 读取数据(发送一个空字节来获取返回数据)
    spi_masttrans(SPI1, buffer, buffer, 1);
    GPIO_WriteBit(GPIOA, GPIO_Pin_15, Bit_SET);
    
    // 注意:移除了这里的GPIO初始化,避免干扰SPI功能
    // 如果需要LED指示,应在单独的初始化函数中设置
    
    return buffer[0]; // 返回读取到的数据
}

以USART模块的TXE标志位作中断控制灯闪烁快慢

#include "stm32f10x.h" // 确保包含正确的头文件
#include"delay.h"
#include<stdio.h>
#include"usart.h"

uint16_t a=1000;

void My_boardLED_Init(void);
void usartinit(void);


int main(void)
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
   My_boardLED_Init();
	usartinit();
	My_USART_SendString(USART1,"HELLO");
	
   while(1)
   {
		 GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET);
		 Delay(a);
		 GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_RESET);
		 Delay(a);
   }
}
void USART1_IRQHandler(void)
{
	if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==SET){
	uint8_t da=USART_ReceiveData(USART1);
	if(da=='0'){a=1000;}
	else if(da=='1'){a=200;}
	else if(da=='2'){a=50;}
}
}
void usartinit(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1,ENABLE);
	GPIO_InitTypeDef in;
	in.GPIO_Mode=GPIO_Mode_AF_PP;
	in.GPIO_Pin=GPIO_Pin_9;
	in.GPIO_Speed=GPIO_Speed_2MHz;
	GPIO_Init(GPIOA,&in);
	in.GPIO_Mode=GPIO_Mode_IPU;
	in.GPIO_Pin=GPIO_Pin_10;
	GPIO_Init(GPIOA,&in);
	
	USART_InitTypeDef us;
	us.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
	us.USART_BaudRate=115200;
	us.USART_Mode=USART_Mode_Rx | USART_Mode_Tx;
	us.USART_Parity=USART_Parity_No;
	us.USART_StopBits=USART_StopBits_1;
	us.USART_WordLength=USART_WordLength_8b;
	USART_Init(USART1,&us);
	USART_Cmd(USART1,ENABLE);//必合总开关
	//配置中断
	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
	//配置NVIC
	NVIC_InitTypeDef nvic;
	nvic.NVIC_IRQChannel=USART1_IRQn;
	nvic.NVIC_IRQChannelPreemptionPriority=0;
	nvic.NVIC_IRQChannelSubPriority=0;
	nvic.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&nvic);
}

void My_boardLED_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
	GPIO_InitTypeDef in;
	in.GPIO_Mode=GPIO_Mode_Out_OD;
	in.GPIO_Pin=GPIO_Pin_13;
	in.GPIO_Speed=GPIO_Speed_2MHz;
	GPIO_Init(GPIOC,&in);

}


tim模块实现延迟

void tim3_init(void)
{
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);  // 使能定时器3的时钟(外设必须使能时钟才能工作)
    
    // 配置定时器时基参数
    TIM_TimeBaseInitTypeDef tim;               // 定义定时器初始化结构体
    tim.TIM_Prescaler=71;                      // 预分频器:72MHz/(71+1)=1MHz(定时器计数频率)
    tim.TIM_Period=999;                        // 自动重装载值:计数到999后触发更新事件(1MHz/1000=1kHz,即1ms触发一次)
    tim.TIM_CounterMode=TIM_CounterMode_Up;    // 计数模式:向上计数(从0到999循环)
    tim.TIM_RepetitionCounter=0;               // 重复计数器:不使用(高级定时器才需要)
    TIM_TimeBaseInit(TIM3,&tim);               // 应用配置到定时器3
    
    TIM_Cmd(TIM3,ENABLE);  // 使能定时器3(开始计数)
    
    // 配置定时器更新中断
    TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);  // 允许定时器3的更新事件产生中断
    
    // 配置中断控制器(NVIC)
    NVIC_InitTypeDef nv;                      // 定义NVIC初始化结构体
    nv.NVIC_IRQChannel=TIM3_IRQn;             // 中断通道:定时器3中断
    nv.NVIC_IRQChannelPreemptionPriority=0;   // 抢占优先级:0(数值越小优先级越高)
    nv.NVIC_IRQChannelSubPriority=0;          // 子优先级:0
    nv.NVIC_IRQChannelCmd=ENABLE;             // 使能该中断通道
    NVIC_Init(&nv);                           // 应用配置到NVIC
}
void TIM3_IRQHandler(void)  // 定时器3中断的入口函数(函数名固定,由启动文件定义)
{
    if(TIM_GetFlagStatus(TIM3,TIM_FLAG_Update)==SET)  // 检查是否是定时器更新事件触发的中断
    {
        TIM_ClearFlag(TIM3,TIM_FLAG_Update);  // 清除更新事件标志位(必须手动清除,否则会持续触发中断)
        currenttim++;                         // 每1ms触发一次中断,将时间计数器加1(实现毫秒计时)
    }
}
void mt_delay(uint32_t ms)
{
    uint32_t pre=currenttim+ms;  // 计算目标时间(当前时间+要延时的毫秒数)
    while(currenttim<pre);       // 循环等待,直到currenttim达到目标时间(实现延时)
}
int main(void)
{
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  // 配置中断优先级分组为第2组(2位抢占优先级,2位子优先级)
    tim3_init();                                     // 初始化定时器3(用于提供时间基准)
    My_boardLED_Init();                              // 初始化LED引脚
    
    while(1)  // 主循环(程序会一直在此循环中运行)
    {
        GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET);  // 设置PC13引脚为高电平(原代码错误:两次均为高电平,无法闪烁)
        mt_delay(500);                             // 延时500毫秒
        GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET);  // 再次设置PC13为高电平(逻辑错误)
        mt_delay(100);                             // 延时100毫秒
    }
}

实现呼吸灯

int main(void)
{
    init();  // 初始化硬件配置
    while(1)  // 主循环,程序将一直运行
    {
        // 获取当前时间(秒级),假设GetTick()返回毫秒数
        float t = GetTick() * 1.0e-3f;
        
        // 计算占空比:生成0~1之间变化的正弦曲线
        // sin()函数输出范围是-1~1,加1后变成0~2,乘以0.5后变成0~1
        float duty = 0.5 * (sin(2 * 3.14 * t) + 1);
        
        // 将占空比转换为定时器比较值(0~1000)
        // 因为定时器周期设置为999,所以范围是0~1000
        uint16_t ccrl = duty * 1000;
        
        // 设置TIM1的通道1比较值,改变PWM占空比
        TIM_SetCompare1(TIM1, ccrl);
    }
}
void init(void)
{
    GPIO_InitTypeDef in;  // 定义GPIO初始化结构体
in.GPIO_Mode = GPIO_Mode_AF_PP;  // 复用推挽输出模式(用于PWM输出)
in.GPIO_Pin = GPIO_Pin_8;  // 选择PA8引脚
in.GPIO_Speed = GPIO_Speed_2MHz;  // 引脚速度为2MHz
GPIO_Init(GPIOA, &in);  // 初始化GPIOA

in.GPIO_Pin = GPIO_Pin_13;  // 选择PB13引脚
GPIO_Init(GPIOB, &in);  // 初始化GPIOB
// 使能TIM1定时器时钟(TIM1在APB2总线上)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);

TIM_TimeBaseInitTypeDef tim;  // 定义定时器基本结构体
tim.TIM_CounterMode = TIM_CounterMode_Up;  // 向上计数模式
tim.TIM_Period = 999;  // 自动重装载值(ARR),计数到999后重置
tim.TIM_Prescaler = 71;  // 预分频值,72MHz/(71+1)=1MHz
tim.TIM_RepetitionCounter = 0;  // 重复计数器(高级定时器特有,这里不用)
TIM_TimeBaseInit(TIM1, &tim);  // 初始化定时器基本参数

// 使能ARR寄存器预加载功能
TIM_ARRPreloadConfig(TIM1, ENABLE);

// 启动定时器计数
TIM_Cmd(TIM1, ENABLE);
TIM_OCInitTypeDef oc;  // 定义输出比较结构体
oc.TIM_OCMode = TIM_OCMode_PWM1;  // PWM模式1:计数器<比较值时输出有效电平
oc.TIM_OCNPolarity = TIM_OCNPolarity_High;  // 互补输出极性(高电平有效)
oc.TIM_OCPolarity = TIM_OCPolarity_High;  // 主输出极性(高电平有效)
oc.TIM_OutputNState = TIM_OutputNState_Enable;  // 使能互补输出
oc.TIM_OutputState = TIM_OutputState_Enable;  // 使能主输出
oc.TIM_Pulse = 0;  // 初始比较值(占空比0)
TIM_OC1Init(TIM1, &oc);  // 初始化TIM1的通道1

// 使能TIM1的PWM输出(高级定时器特有,必须调用)
TIM_CtrlPWMOutputs(TIM1, ENABLE);

// 使能捕获比较预加载功能
TIM_CCPreloadControl(TIM1, ENABLE);
}

使用定时器进行超声波测距

#include "stm32f10x.h" // 确保包含正确的头文件
#include"delay.h"
#include<stdio.h>
#include"usart.h"
#include"usart.h"


void usart_init(void);
void tim_init(void);

int main(void)
{
    usart_init();
    tim_init();  // 初始化定时器,之前缺失
    
    My_USART_SendString(USART1, "hello world\r\n");
    
    while(1)
    {
        // 1. 向计数器写入0
        TIM_SetCounter(TIM1, 0);
        
        // 2. 清除捕获标志位
        TIM_ClearFlag(TIM1, TIM_FLAG_CC1 | TIM_FLAG_CC2);
        
        // 3. 开启定时器
        TIM_Cmd(TIM1, ENABLE);
        
        // 4. 向TRIG引脚发送10us脉冲
        GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
        DelayUs(10);
        GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET);
        
        // 5. 等待上升沿捕获(回声开始)
        uint32_t timeout = 0;
        while(TIM_GetFlagStatus(TIM1, TIM_FLAG_CC1) == RESET)
        {
            DelayUs(1);
            if(++timeout > 10000)  // 超时处理,防止死等
            {
                break;
            }
        }
        
        // 6. 等待下降沿捕获(回声结束)
        timeout = 0;
        while(TIM_GetFlagStatus(TIM1, TIM_FLAG_CC2) == RESET)
        {
            DelayUs(1);
            if(++timeout > 50000)  // 约5米测距上限
            {
                break;
            }
        }
        
        // 7. 关闭定时器
        TIM_Cmd(TIM1, DISABLE);
        
        // 8. 计算距离
        if(timeout <= 50000)  // 未超时
        {
            uint16_t ccr1 = TIM_GetCapture1(TIM1);  // 上升沿时间
            uint16_t ccr2 = TIM_GetCapture2(TIM1);  // 下降沿时间
            uint32_t time_diff;
            
            // 处理计数器溢出情况
            if(ccr2 >= ccr1)
            {
                time_diff = ccr2 - ccr1;
            }
            else
            {
                time_diff = (65535 - ccr1) + ccr2;
            }
            
            // 计算距离:时间(us) * 声速(340m/s) / 2(往返)
            float dis = time_diff * 0.034f / 2.0f;
            My_USART_Printf(USART1, "dis=%.2f cm\r\n", dis);
        }
        else
        {
            My_USART_SendString(USART1, "Distance out of range\r\n");
        }
        
        Delay(100);  // 测量间隔
    }
}

void tim_init(void)
{
    // 使能定时器1时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
    
    // 定时器基本配置
    TIM_TimeBaseInitTypeDef ti;
    ti.TIM_CounterMode = TIM_CounterMode_Up;
    ti.TIM_Period = 65535;  // 最大计数
    ti.TIM_Prescaler = 71;  // 72MHz / (71+1) = 1MHz,计数频率1us
    ti.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM1, &ti);
    
    // 初始化ECHO引脚 PA8 (TIM1_CH1)
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    GPIO_InitTypeDef in;
    in.GPIO_Mode = GPIO_Mode_IPD;  // 下拉输入
    in.GPIO_Pin = GPIO_Pin_8;
    in.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &in);
    
    // 初始化输入捕获通道1(上升沿)
    TIM_ICInitTypeDef i;
    i.TIM_Channel = TIM_Channel_1;
    i.TIM_ICFilter = 6;  // 增加滤波,减少干扰
    i.TIM_ICPolarity = TIM_ICPolarity_Rising;  // 上升沿捕获
    i.TIM_ICPrescaler = TIM_ICPSC_DIV1;
    i.TIM_ICSelection = TIM_ICSelection_DirectTI;
    TIM_ICInit(TIM1, &i);
    
    // 初始化输入捕获通道2(下降沿)
    i.TIM_Channel = TIM_Channel_2;
    i.TIM_ICFilter = 6;
    i.TIM_ICPolarity = TIM_ICPolarity_Falling;  // 下降沿捕获
    i.TIM_ICPrescaler = TIM_ICPSC_DIV1;
    i.TIM_ICSelection = TIM_ICSelection_IndirectTI;  // 间接映射到TI1
    TIM_ICInit(TIM1, &i);
    
    // 初始化TRIG引脚 PA0
    GPIO_InitTypeDef g;
    g.GPIO_Mode = GPIO_Mode_Out_PP;
    g.GPIO_Pin = GPIO_Pin_0;
    g.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &g);
}

void usart_init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);
    
    // 配置USART1_TX (PA9)
    GPIO_InitTypeDef in;
    in.GPIO_Mode = GPIO_Mode_AF_PP;
    in.GPIO_Pin = GPIO_Pin_9;
    in.GPIO_Speed = GPIO_Speed_50MHz;  // 提高速度
    GPIO_Init(GPIOA, &in);
    
    // 配置USART1_RX (PA10)
    in.GPIO_Pin = GPIO_Pin_10;
    in.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOA, &in);
    
    // USART初始化参数
    USART_InitTypeDef i;
    i.USART_BaudRate = 115200;
    i.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    i.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    i.USART_Parity = USART_Parity_No;
    i.USART_StopBits = USART_StopBits_1;
    i.USART_WordLength = USART_WordLength_8b;
    USART_Init(USART1, &i);
    
    USART_Cmd(USART1, ENABLE);
}

PWM捕获

#include "stm32f10x.h"
#include "delay.h"
#include "stdio.h"
#include "usart.h"

// 函数声明
void usart_init(void);
void tim3_init(void);
void tim1_init(void);
void My_USART_SendString(USART_TypeDef* USARTx, char* str);
void My_USART_Printf(USART_TypeDef* USARTx, const char* format, ...);
void Delay(uint32_t ms);

int main(void)
{
    // 初始化外设
    usart_init();
    tim3_init();    // 初始化TIM3用于PWM输出
    tim1_init();    // 初始化TIM1用于输入捕获
    delay_init();   // 初始化延时函数
    
    // 发送初始信息
    My_USART_SendString(USART1, "你好世界\r\n");
    
    // 设置TIM3的PWM占空比(周期1000,这里设置为20%)
    TIM_SetCompare1(TIM3, 200);
   
    while(1)
    {
        // 等待TIM1捕获到上升沿触发
        while(TIM_GetFlagStatus(TIM1, TIM_FLAG_CC1) == RESET);
        TIM_ClearFlag(TIM1, TIM_FLAG_CC1);
        
        // 读取捕获值
        uint16_t ccr1 = TIM_GetCapture1(TIM1);  // 周期捕获值
        uint16_t ccr2 = TIM_GetCapture2(TIM1);  // 占空比捕获值
        
        // 计算周期和占空比(定时器时钟为1MHz,所以1个计数单位=1us)
        float period = ccr1 * 1.0e-3f;  // 转换为ms
        float duty = ((float)ccr2 / ccr1) * 100.0f;
        
        // 串口输出结果
        My_USART_Printf(USART1, "周期=%.3fms, 占空比=%.2f%%\r\n", period, duty);
        
        // 延时500ms再进行下一次测量
        Delay(500);
    }
}

/**
 * TIM1初始化:输入捕获模式,用于测量PWM信号的周期和占空比
 * 通道1:上升沿捕获(测量周期)
 * 通道2:下降沿捕获(测量占空比)
 */
void tim1_init(void)
{
    // 使能TIM1和GPIOA时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 | RCC_APB2Periph_GPIOA, ENABLE);
    
    // 配置时基单元:72MHz / (71+1) = 1MHz,最大计数65535
    TIM_TimeBaseInitTypeDef tim_base;
    tim_base.TIM_CounterMode = TIM_CounterMode_Up;
    tim_base.TIM_Period = 65535;          // 最大计数
    tim_base.TIM_Prescaler = 71;          // 预分频,72MHz/72=1MHz
    tim_base.TIM_ClockDivision = 0;       // 时钟分割
    tim_base.TIM_RepetitionCounter = 0;   // 重复计数器(高级定时器特有)
    TIM_TimeBaseInit(TIM1, &tim_base);
    
    // 配置PA8为TIM1_CH1输入(上拉输入)
    GPIO_InitTypeDef gpio;
    gpio.GPIO_Mode = GPIO_Mode_IPU;       // 上拉输入
    gpio.GPIO_Pin = GPIO_Pin_8;           // TIM1_CH1
    gpio.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &gpio);
    
    // 初始化输入捕获通道1(上升沿)
    TIM_ICInitTypeDef tim_ic;
    tim_ic.TIM_Channel = TIM_Channel_1;
    tim_ic.TIM_ICFilter = 0x0F;           // 较强滤波,减少噪声影响
    tim_ic.TIM_ICPolarity = TIM_ICPolarity_Rising;  // 上升沿捕获
    tim_ic.TIM_ICPrescaler = TIM_ICPSC_DIV1;        // 不分频
    tim_ic.TIM_ICSelection = TIM_ICSelection_DirectTI; // 直接映射到TI1
    TIM_ICInit(TIM1, &tim_ic);
    
    // 初始化输入捕获通道2(下降沿)
    tim_ic.TIM_Channel = TIM_Channel_2;
    tim_ic.TIM_ICPolarity = TIM_ICPolarity_Falling; // 下降沿捕获
    tim_ic.TIM_ICSelection = TIM_ICSelection_IndirectTI; // 间接映射到TI1
    TIM_ICInit(TIM1, &tim_ic);
    
    // 配置从模式:当捕获到上升沿时复位计数器
    TIM_SelectInputTrigger(TIM1, TIM_TS_TI1FP1);    // 选择TI1FP1作为触发源
    TIM_SelectSlaveMode(TIM1, TIM_SlaveMode_Reset); // 触发时复位计数器
    
    // 使能TIM1
    TIM_Cmd(TIM1, ENABLE);
}

/**
 * TIM3初始化:PWM输出模式,用于产生PWM信号
 * 通道1输出PWM到PA6
 */
void tim3_init(void)
{
    // 使能TIM3和GPIOA时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    
    // 配置时基单元:72MHz/(71+1) = 1MHz,周期1000→1kHz PWM
    TIM_TimeBaseInitTypeDef tim_base;
    tim_base.TIM_CounterMode = TIM_CounterMode_Up;
    tim_base.TIM_Period = 999;            // 周期=1000-1
    tim_base.TIM_Prescaler = 71;          // 预分频
    tim_base.TIM_ClockDivision = 0;
    TIM_TimeBaseInit(TIM3, &tim_base);
    
    // 使能ARR预加载
    TIM_ARRPreloadConfig(TIM3, ENABLE);
    
    // 配置PA6为TIM3_CH1复用推挽输出
    GPIO_InitTypeDef gpio;
    gpio.GPIO_Mode = GPIO_Mode_AF_PP;     // 复用推挽输出
    gpio.GPIO_Pin = GPIO_Pin_6;           // TIM3_CH1
    gpio.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &gpio);
    
    // 配置PWM模式1
    TIM_OCInitTypeDef tim_oc;
    tim_oc.TIM_OCMode = TIM_OCMode_PWM1;          // PWM模式1
    tim_oc.TIM_OCPolarity = TIM_OCPolarity_High;  // 输出极性高
    tim_oc.TIM_OutputState = TIM_OutputState_Enable; // 使能输出
    tim_oc.TIM_Pulse = 0;                        // 初始占空比0
    TIM_OC1Init(TIM3, &tim_oc);
    
    // 使能CCR1预加载
    TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
    
    // 使能TIM3
    TIM_Cmd(TIM3, ENABLE);
}

/**
 * USART1初始化:用于串口通信,仅发送模式
 */
void usart_init(void)
{
    // 使能USART1和GPIOA时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
    
    // 配置PA9为USART1_TX复用推挽输出
    GPIO_InitTypeDef gpio;
    gpio.GPIO_Mode = GPIO_Mode_AF_PP;     // 复用推挽输出
    gpio.GPIO_Pin = GPIO_Pin_9;           // USART1_TX
    gpio.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &gpio);
    
    // 配置USART1:115200波特率,8位数据,无校验,1个停止位
    USART_InitTypeDef usart;
    usart.USART_BaudRate = 115200;
    usart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    usart.USART_Mode = USART_Mode_Tx;     // 仅发送模式
    usart.USART_Parity = USART_Parity_No;
    usart.USART_StopBits = USART_StopBits_1;
    usart.USART_WordLength = USART_WordLength_8b;
    USART_Init(USART1, &usart);
    
    // 使能USART1
    USART_Cmd(USART1, ENABLE);
}

// 串口发送一个字节
void My_USART_SendByte(USART_TypeDef* USARTx, uint8_t data)
{
    while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);
    USART_SendData(USARTx, data);
    while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET);
}

// 串口发送字符串
void My_USART_SendString(USART_TypeDef* USARTx, char* str)
{
    while(*str != '\0')
    {
        My_USART_SendByte(USARTx, *str++);
    }
}

// 串口printf函数实现
#include <stdarg.h>
void My_USART_Printf(USART_TypeDef* USARTx, const char* format, ...)
{
    char buffer[128];
    va_list args;
    va_start(args, format);
    vsprintf(buffer, format, args);
    va_end(args);
    My_USART_SendString(USARTx, buffer);
}
    

使用ADC模拟信号(光敏控制板载led(常规序列

#include "stm32f10x.h"
#include "delay.h"
#include <stdio.h>
#include "usart.h"

void ADC1_init(void);

int main(void)
{
    ADC1_init();
    
    // 使能GPIOC时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13;
    // 改为推挽输出,无需外部上拉
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_Init(GPIOC, &GPIO_InitStruct);
    
    while(1)
    {
        // 清除转换完成标志
        ADC_ClearFlag(ADC1, ADC_FLAG_EOC);
        // 启动软件转换
        ADC_SoftwareStartConvCmd(ADC1, ENABLE);
        // 等待转换完成
        while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
        // 读取转换值
        uint16_t dr = ADC_GetConversionValue(ADC1);
        // 计算电压值
        float v = dr * (3.3f / 4095);
        
        // 根据电压控制LED
        if(v > 1.5f)
        {
            // 电压高于1.5V,LED亮
            GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_RESET);
        }
        else
        {
            // 电压低于等于1.5V,LED灭
            GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_SET);
        }
        
        // 可以添加适当延时,避免频繁转换
        delay_ms(100);
    }
}

void ADC1_init(void)
{
    // 使能GPIOA时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    
    // 配置PA0为模拟输入
    GPIO_InitTypeDef in;
    in.GPIO_Pin = GPIO_Pin_0;
    in.GPIO_Mode = GPIO_Mode_AIN;  // 模拟输入模式
    GPIO_Init(GPIOA, &in);
    
    // 配置ADC时钟 (PCLK2/6 = 72MHz/6 = 12MHz)
    RCC_ADCCLKConfig(RCC_PCLK2_Div6);
    // 使能ADC1时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
    
    // 初始化ADC
    ADC_InitTypeDef adc;
    adc.ADC_ContinuousConvMode = DISABLE;  // 单次转换模式
    adc.ADC_DataAlign = ADC_DataAlign_Right;  // 右对齐
    adc.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;  // 无外部触发
    adc.ADC_Mode = ADC_Mode_Independent;  // 独立模式
    adc.ADC_NbrOfChannel = 1;  // 1个转换通道
    adc.ADC_ScanConvMode = DISABLE;  // 非扫描模式
    ADC_Init(ADC1, &adc);
    
    // 配置规则通道:通道0,序号1,采样时间13.5周期
    ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_13Cycles5);
    
    // 关闭外部触发转换(我们使用软件触发)
    ADC_ExternalTrigConvCmd(ADC1, DISABLE);
    
    // 使能ADC1
    ADC_Cmd(ADC1, ENABLE);
    
    // 添加ADC校准步骤(重要)
    ADC_ResetCalibration(ADC1);
    while(ADC_GetResetCalibrationStatus(ADC1));
    ADC_StartCalibration(ADC1);
    while(ADC_GetCalibrationStatus(ADC1));
}

ADC捕捉电压变化

#include "stm32f10x.h" // 
#include"delay.h"
#include<stdio.h>
#include"usart.h"

void usart_init(void);
void tim1_init(void);
void adc_init(void);
int main(void)
{
	
	usart_init();
	tim1_init();
	adc_init();
	My_USART_SendString(USART1,"hello");
  while(1)
  {
    while(ADC_GetFlagStatus(ADC1,ADC_FLAG_JEOC)==RESET);
		uint16_t jdr1=ADC_GetInjectedConversionValue(ADC1,ADC_InjectedChannel_1);
		ADC_ClearFlag(ADC1,ADC_FLAG_JEOC);
		float v=jdr1 *(3.3f/4095);
		My_USART_Printf(USART1,"%.3f\n",v);
	}
}
void adc_init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	GPIO_InitTypeDef gpio={0};
	gpio.GPIO_Mode=GPIO_Mode_AIN;
	gpio.GPIO_Pin=GPIO_Pin_0;
	GPIO_Init(GPIOA,&gpio);
	//配置ADC模块时钟
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
	//配置ADC基本参数
	ADC_InitTypeDef adc={0};
	adc.ADC_ContinuousConvMode=DISABLE;//不知
	adc.ADC_DataAlign=ADC_DataAlign_Right;
	adc.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;//不知
	adc.ADC_Mode=ADC_Mode_Independent;//不知
	adc.ADC_NbrOfChannel=1;
	adc.ADC_ScanConvMode=DISABLE;
	ADC_Init(ADC1,&adc);
	//注入序列额外参数
	ADC_InjectedSequencerLengthConfig(ADC1,1);
	ADC_ExternalTrigInjectedConvConfig(ADC1,ADC_ExternalTrigInjecConv_T1_TRGO);
	ADC_ExternalTrigInjectedConvCmd(ADC1,ENABLE);
	ADC_InjectedChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_13Cycles5);
	ADC_Cmd(ADC1,ENABLE);
}
void tim1_init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
	TIM_TimeBaseInitTypeDef tim;
	tim.TIM_CounterMode=TIM_CounterMode_Up;
	tim.TIM_Period=999;
	tim.TIM_Prescaler=71;
	tim.TIM_RepetitionCounter=0;
	TIM_TimeBaseInit(TIM1,&tim);
	TIM_SelectOutputTrigger(TIM1,TIM_TRGOSource_Update);//TRGO:Update
	TIM_Cmd(TIM1,ENABLE);
}
void usart_init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	GPIO_InitTypeDef in={0};
	in.GPIO_Pin=GPIO_Pin_9;
	in.GPIO_Mode=GPIO_Mode_AF_PP;
	in.GPIO_Speed=GPIO_Speed_2MHz;
	GPIO_Init(GPIOA,&in);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	USART_InitTypeDef usa;
	usa.USART_BaudRate=115200;
	usa.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
	usa.USART_Mode=USART_Mode_Tx;
	usa.USART_Parity=USART_Parity_No;
	usa.USART_StopBits=USART_StopBits_1;
	usa.USART_WordLength=USART_WordLength_8b;
	USART_Init(USART1,&usa);
	USART_Cmd(USART1,ENABLE);
}

本文章已经生成可运行项目
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值