基于STM32F103C8T6开发笔记

                        基于STM32F103C8T6开发笔记

  1. GPIO的配置
  2. 定时器配置
  3. 串口1配置
  4. 串口2配置
  5. 计数器配置
  6. ADC配置
  7. SPI配置
STM32开发笔记
MDK5小技巧:按ctrl+空格可以自动补全;
1.PWM控制LED呼吸灯效果
外设时钟配置
void Rcc_config(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE);//使能GPIOB 时钟和功能复用 IO 时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//使能TIM2 时钟
}

GPIO配置
void Gpio_config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出
	GPIO_Init(GPIOB, &GPIO_InitStructure);
}


定时器配置
void Tim_config(void)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
	TIM_TimeBaseStructure.TIM_Period = 500;//计数长度为19999+1=20000,可得PWM频率为1M/20000=50Hz
	TIM_TimeBaseStructure.TIM_Prescaler = 72;//系统默认时钟为72MHz,预分频71+1次,得到TIM3计数时钟为1MHz
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//设置了时钟分割,TIM_CKD_DIV1为分割;
	TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
//TIM向上计数模式
//	TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2, & TIM_TimeBaseStructure);
	
	GPIO_PinRemapConfig(GPIO_PartialRemap2_TIM2,ENABLE);	//改变指定管脚的映射???
	
	
	TIM_OCInitTypeDef TIM_OCInitStructure;
	TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//选择定时器模式:TIM脉冲宽度调制模式1
	TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//比较输出使能
//	TIM_OCInitStructure.TIM_OutputNState=TIM_OutputNState_Enable;
//使能输出比较 N 状态
	TIM_OCInitStructure.TIM_Pulse=250;//设置了待装入捕获比较寄存器的脉冲值
	TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;//输出极性:TIM输出比较极性高
//	TIM_OCInitStructure.TIM_OCNPolarity=TIM_OCNPolarity_Low;
//	TIM_OCInitStructure.TIM_OCIdleState=TIM_OCIdleState_Reset;
//	TIM_OCInitStructure.TIM_OCNIdleState=TIM_OCIdleState_Reset;
	TIM_OC3Init(TIM2,&TIM_OCInitStructure);//使能TIMx在CCR2上的预装载寄存器,OCx确定了是channlex,要是OC3则是channel 3 
	
	TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable);//使能TIMx在ARR上的预装载寄存器 
	//TIM_CtrlPWMOutputs(TIM2,ENABLE);//设置TIM2的PWM输出为使能
	TIM_Cmd(TIM2,ENABLE);//使能TIMx外设

}
延迟函数
void delayms(u32 i)
{
	u32	temp;
	SysTick->LOAD=9000*i;
	SysTick->CTRL=0X01;
	SysTick->VAL=0X00;
	do
	{
		temp=SysTick->CTRL;
	}
	while((temp&0x01)&&(!(temp&(1<<16))));
	SysTick->CTRL=0X00;
	SysTick->VAL=0X00;
}
主函数
int main(void)
{
	u16 i;
	Rcc_config();
	Gpio_config();
	Tim_config();
	while(1)
	{
			for(i=0;i<300;i++)
		{
			TIM_SetCompare3(TIM2, i);//设置 TIMx 捕获比较 3 寄存器值 channelx x是几TIM_SetComparex x是几;
			delayms(10);
		}
	}

}
颜色传感器调
 51部分:
波特率计算公式:TH1=256-(Fsoc×2smod)/(12×32×Baud)
Fsoc:晶振频率,单位HZ
SMOD:波特率加倍smod=1,不加倍smod=0;
Baud:波特率
机器周期 = 12*时钟周期=12/晶振频率(MHZ)us   12M晶振机械周期为1us
计数初值高8位(TH1)=(满计数值-定时时间/机械周期)/256;
计数初值低8位(TL1)=(满计数值-定时时间/机械周期)%256;

.
下面给出52定时器2的串口波特率初始化函数:
.
void Uart0_Init()
.
{
.
    RCAP2L=0xD9;//9600波特率对应 FFD9,低位为D9
.
    RCAP2H=0xFF;//高位为FF
.
    T2CON=0x34;//RCLK、TCLK、TR2置1
.
    SCON=0x50;//串口工作模式1,接收使能
.
    ES=1;//打开接收中断
.
    EA=1;//打开总中断
.
}
.
.
5
.
中断函数:
.
void Uart0_Ist() interrupt 4 //中断函数
.
{
.
       if(RI)
.
    {
.
        RI= 0;
.
        //Do whatever you want;
.
    }
.
       if(TI)
.
    {
.
        TI = 0;
.
        //Do whatever you want;
.
    }
.
}
STM32部分:
int main(void)
{
	RCC_config();
	Gpio_config();
	TIM2_config();
	TIM3_config();
	uart1_init();
	nvid_init();
	
	while(1)
	{
	}

STM32串口通讯
串口1配置:
#ifndef _CONFIG_H
#define _CONFIG_H
#include
void sys_init(void);
void gpio_init(void);
void uart1_init(void);
void nvid_init(void);
void USART1_IRQHandler(void);
#endif

#include"config.h"
void sys_init(void)
{
	SystemInit();
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE);	
}
void gpio_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 ;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP ;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 ;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING ;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void uart1_init(void)
{
	USART_InitTypeDef USART_InitStructure;
	USART_InitStructure.USART_BaudRate = 9600;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl =USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
	USART_Init(USART1, &USART_InitStructure);

	USART_Cmd(USART1, ENABLE);
	USART_ITConfig(USART1, USART_IT_RXNE,ENABLE);
	USART_ClearFlag(USART1,USART_FLAG_RXNE|USART_FLAG_TC|USART_FLAG_TXE);
}

void nvid_init(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;	
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

}


void USART1_IRQHandler(void)
{
	u8 k;
	if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)//检查指定的USART中断发生与否
	{
		k=USART_ReceiveData(USART1);
		USART_SendData(USART1,k);//通过外设USARTx发送单个数据
		//USART_ReceiveData(USART1)返回USARTx最近接收到的数据
	
		while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
	}
}
#include"config.h"

int main(void)
{
	sys_init();
	gpio_init();
	uart1_init();
	nvid_init();
	while(1);
}

串口2配置:
int main()
{
	RCCINIT();	   //系统时钟的初始化
	GPIOINIT();	   // 端口的初始化
	USARTINIT();   // 串口的配置及其初始化
	NVICINIT();		// 中断模式的初始化
	while(1);
}
void RCCINIT()			//系统时钟的初始化配置
{
	SystemInit();//72m
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB,ENABLE);
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
}
void GPIOINIT()			   //端口的初始化配置
{
	GPIO_InitTypeDef GPIO_InitStructure;	
	
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2;//TX
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
	GPIO_Init(GPIOA,&GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3;//RX
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	GPIO_SetBits(GPIOB,GPIO_Pin_12);

}
void USARTINIT()		   //通讯串口的配置
{
	USART_InitTypeDef  USART_InitStructure;

	USART_InitStructure.USART_BaudRate=9600;   //波特率设置为9600
	USART_InitStructure.USART_WordLength=USART_WordLength_8b;
	USART_InitStructure.USART_StopBits=USART_StopBits_1;
	USART_InitStructure.USART_Parity=USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;

	USART_Init(USART2,&USART_InitStructure);

	USART_Cmd(USART2, ENABLE);
	USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//使能或者失能指定的USART中断 接收中断
	USART_ClearFlag(USART2,USART_FLAG_TC);//清除USARTx的待处理标志位
}
void NVICINIT()				//中断模式的配置
{
	NVIC_InitTypeDef NVIC_InitStructure; 

	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); 

	NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; 
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; 
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
	NVIC_Init(&NVIC_InitStructure);
}
void USART2_IRQHandler(void)
{
	u8 k;
	GPIO_ResetBits(GPIOB,GPIO_Pin_12);
	if(USART_GetITStatus(USART2,USART_IT_RXNE)!=RESET)//检查指定的USART中断发生与否
	{
		k=USART_ReceiveData(USART2);
		k++;
		USART_SendData(USART2,k);//通过外设USARTx发送单个数据
		//USART_ReceiveData(USART1)返回USARTx最近接收到的数据
		
		while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);
	}
}



STM32串口printf打印配置
注意:要加入stdio.h头文件
1.RCC配置:
void ADC_RCC_Config(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1|RCC_APB2Periph_USART1, ENABLE);	
}
2.Gpio配置:
void uart1_Gpio_init(void)
{
		GPIO_InitTypeDef GPIO_InitStructure;
		GPIO_InitStructure.GPIO_Pin = Uart1_Txd;
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
		GPIO_Init(GPIOA, &GPIO_InitStructure);

		GPIO_InitStructure.GPIO_Pin = Uart1_Rxd;
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
		GPIO_Init(GPIOA, &GPIO_InitStructure);	


}
3.uart1初始化:
void uart1_init(void)
{
	USART_InitTypeDef USART_InitStructure;
	USART_InitStructure.USART_BaudRate = 9600;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl =USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
	USART_Init(USART1, &USART_InitStructure);


	USART_ITConfig(USART1, USART_IT_RXNE,ENABLE);
	USART_ClearFlag(USART1,USART_FLAG_RXNE|USART_FLAG_TC|USART_FLAG_TXE);
	USART_Cmd(USART1, ENABLE);		
}
4.串口中断初始化:
void nvic_uart1(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;	
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

}
5.输入输出初始化函数:
int fputc(int ch, FILE *f)
{
		/* 发送一个字节数据到USART1 */
		USART_SendData(USART1, (uint8_t) ch);
		/* 等待发送完毕 */
		while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
		return (ch);
}

/// 重定向c库函数scanf到USART1
int fgetc(FILE *f)
{
		/* 等待串口1输入数据 */
		while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);
		return (int)USART_ReceiveData(USART1);
}




STM32定时器2控制led
Tout= ((999+1)*(71+1))/Tclk;
其中:
TIM_Period: 999(1000-1) 定时周期为1000
TIM_Prescaler:71(72-1) 分频系数72
Tclk: TIM1 的输入时钟频率(单位为 Mhz)。
Tout: TIM1 溢出时间(单位为 us)。
这里我们设置溢出时间为: 72000/72M = 1000us = 1ms

注意:每次进入中断服务程序间隔时间为
((1+TIM_Prescaler )/72M)*(1+TIM_Period )=((1+7199)/72M)*(1+9999)=1秒*/
TIM_Prescaler://分频35999      72000k/(35999+1)/2=1Hz 1秒中断溢出一次
TIM_Period://计数次数TIM_Period=秒/((1+TIM_Prescaler )/72000000)-1;

由上式得:
1.SYSTEM CLOCK CONFIG;(RCC)//在main函数中必须先调用RCC再调用别的函数;
2.LED GPIO CONFIG;
3.NVIC CONFIG;
4.TIMX CONFIG;
5.TIMX HANDLER FUNCTION;
#include

/*1.LED GPIO CONFIG;*/
void Gpio_config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
	GPIO_Init(GPIOB, &GPIO_InitStructure);

}

/*2.SYSTEM CLOCK CONFIG;(RCC)*/
void Sys_config(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//GPIOB CLOCK OPENED;
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//TIM3 CLOCK OPENED;
}

/*3.NVIC CONFIG;*/
void Nvic_config(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
	NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&NVIC_InitStructure);


}
/*4.TIMX CONFIG;*/
void Tim3_config(void)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
	
	TIM_ClearITPendingBit(TIM2, TIM_IT_Update);//清除 TIMx 的中断待处理位
	
	TIM_TimeBaseStructure.TIM_Period = 1000;
	TIM_TimeBaseStructure.TIM_Prescaler = 35999;
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInit(TIM3, & TIM_TimeBaseStructure);
	TIM_Cmd(TIM3, ENABLE);//使能或者失能 TIMx 外设
	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);//使能或者失能指定的 TIM 中断
}
#include
void TIM3_IRQHandler(void)
{
	u8 ReadValue;
	TIM_ClearITPendingBit(TIM3,TIM_IT_Update);//清除 TIMx 的中断待处理位
	ReadValue = GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_8);
	if(ReadValue==Bit_RESET) GPIO_SetBits(GPIOB,GPIO_Pin_8);
	else GPIO_ResetBits(GPIOB,GPIO_Pin_8);
}

int main(void) 
{
	Sys_config();
	Gpio_config();
	Tim3_config();
	Nvic_config();
	while(1);
}
STM32计数器
第一步,设置RCC
第二步:设置GPIO
第三步,设置定时器模式
第四步,可以在主函数中读取计数器的值,其它的应用,就看具体的情况了。
STM32超声波模块
1.系统时钟RCC初始化
2.GPIO初始化
3.定时器初始化
Tout= ((999+1)*(71+1))/Tclk;
其中:
TIM_Period: 999(1000-1) 定时周期为1000系统时钟振荡1000次,一次1us;
TIM_Prescaler:71(72-1) 分频系数72
Tclk: TIM1 的输入时钟频率(单位为 Mhz)。
Tout: TIM1 溢出时间(单位为 us)。
这里我们设置溢出时间为: 72000/72M = 1000us = 1ms
4.定时器中断初始化
5.中断函数作用
6.超声波距离测试算法:
1.先使用STM32的数字引脚向TRIG脚输入至少10us的高电平信号,触发模块的测距功能。然后将管脚拉低;
测距功能触发后,模块将自动发出 8 个 40kHz 的超声波脉冲,并自动检测是否有信号返回,这一步由模块内部自动完成。
2.一旦检测到有回波信号则ECHO引脚会输出高电平。高电平持续的时间就是超声波从发射到返回的时间。此时可以使用定时器获取高电平的时间, 并计算出距被测物体的实际距离。公式: 距离=高电平时间*声速(340M/S)/2;
7.主函数使用
#include "config.h"

#ifdef ultrasonic

void Ultrasonic_init(void)
{
	 Rcc_init();
	 Gpio_init();
	 TIM2_init();
	 uart1_init();
	 NVIC_init();
	 nvic_uart1();

}

void Ultrasonic_Enable(void)
{
	printf("%d\n",Distance_test());

}



void Rcc_init(void)
{
	SystemInit();
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_USART1,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	

}	

void Gpio_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE);
	GPIO_InitStructure.GPIO_Pin = Echo;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = Trig;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Pin = Uart1_Txd;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = Uart1_Rxd;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOA, &GPIO_InitStructure);	

	
//	/**debug**/
//	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
//	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
//	GPIO_Init(GPIOB, &GPIO_InitStructure);
//	
//	GPIO_ResetBits(GPIOB,GPIO_Pin_15);
}

void TIM2_init(void)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
	
	TIM_DeInit(TIM2);
	TIM_TimeBaseStructure.TIM_Period = 999;
	TIM_TimeBaseStructure.TIM_Prescaler = 71;
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInit(TIM2, & TIM_TimeBaseStructure);
	
	
	TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
	TIM_Cmd(TIM2,DISABLE);

}
void NVIC_init(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;  
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 5;
	NVIC_Init(&NVIC_InitStructure);
	
	TIM_ITConfig(TIM2, TIM_IT_Update ,ENABLE);
}

void delayus(u32 i)
{
	u32 temp;
	SysTick->LOAD=9*i;		 //设置重装数值, 72MHZ时
	SysTick->CTRL=0X01;		 //使能,减到零是无动作,采用外部时钟源
	SysTick->VAL=0;		   	 //清零计数器
	do
	{
		temp=SysTick->CTRL;		   //读取当前倒计数值
	}
	while((temp&0x01)&&(!(temp&(1<<16))));	 //等待时间到达
	SysTick->CTRL=0;	//关闭计数器
	SysTick->VAL=0;		//清空计数器
}

u16 Distance_test(void)
{
	u16 i;
	for(i=0;i<5;i++)
	{
		GPIO_SetBits(GPIOA,Trig);
		delayus(20);
		GPIO_ResetBits(GPIOA,Trig);
		while(GPIO_ReadInputDataBit(GPIOA, Echo)==RESET);
		TIM_Cmd(TIM2,ENABLE);
		while(GPIO_ReadInputDataBit(GPIOA,Echo)==SET);
		TIM_Cmd(TIM2,DISABLE);
		count=TIM_GetCounter(TIM2);
		Sum+=((count+overtime*1000)/58.0)-3;
		TIM_SetCounter(TIM2,0);
		overtime=0;
	}
	TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
	Sum /= 5;
	return Sum;
	
}


void TIM2_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
	{
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
		overtime++;
	}


}


#endif

#ifdef Uart1_print

/*uart1_init*/
void uart1_init(void)
{
	USART_InitTypeDef USART_InitStructure;
	USART_InitStructure.USART_BaudRate = 9600;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl =USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
	USART_Init(USART1, &USART_InitStructure);


	USART_ITConfig(USART1, USART_IT_RXNE,ENABLE);
	USART_ClearFlag(USART1,USART_FLAG_RXNE|USART_FLAG_TC|USART_FLAG_TXE);
	USART_Cmd(USART1, ENABLE);		
}

void nvic_uart1(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;	
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

}

int fputc(int ch, FILE *f)
{
		/* 发送一个字节数据到USART1 */
		USART_SendData(USART1, (uint8_t) ch);
		
		/* 等待发送完毕 */
		while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);		
	
		return (ch);
}

/// 重定向c库函数scanf到USART1
int fgetc(FILE *f)
{
		/* 等待串口1输入数据 */
		while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);

		return (int)USART_ReceiveData(USART1);
}
#endif
STM32 ADC转换器
1.开启 PA 口时钟和 ADC1 时钟,设置 PA0 为模拟输入。使能 GPIOA 和 ADC 时钟用 RCC_APB2PeriphClockCmd 函数,设置 PA0 的输入方式,使用 GPIO_Init 函数即可。
2. 复位 ADC1,同时设置 ADC1 分频因子。
参数 ADC_Mode 故名是以是用来设置 ADC 的模式。前面讲解过, ADC 的模式非常多,包括独立模式,注入同步模式等等,这里我们选择独立模式,所以参数为 ADC_Mode_Independent。参数 ADC_ScanConvMode 用来设置是否开启扫描模式, 因为是单次转换,这里我们选择不开启值 DISABLE 即可。参数ADC_ContinuousConvMode 用来设置是否开启连续转换模式,因为是单次转换模式,所以我们选择不开启连续转换模式, DISABLE 即可。
参数 ADC_ExternalTrigConv 是用来设置启动规则转换组转换的外部事件,这里我们选择软件触发,选择值为 ADC_ExternalTrigConv_None 即可。参数 DataAlign 用来设置 ADC 数据对齐方式是左对齐还是右对齐,这里我们选择右对齐方式ADC_DataAlign_Right。参数 ADC_NbrOfChannel 用来设置规则序列的长度,这里我们是单次转换,所以值为 1 即可。
通过上面对每个参数的讲解, 下面来看看我们的初始化范例:
ADC 时钟复位的方法是:
ADC_DeInit(ADC1);
分频因子:
RCC_ADCCLKConfig(RCC_PCLK2_Div6);//这个我们设置分频因子位 6, 时钟为 72/6=12MHz,
3.初始化 ADC1 参数, 设置 ADC1 的工作模式以及规则序列的相关信息。
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC 工作模式:独立模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //AD 单通道模式
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //AD 单次转换模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
//转换由软件而不是外部触发启动
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC 数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = 1; //顺序进行规则转换的 ADC 通道的数目 1
ADC_Init(ADC1, &ADC_InitStructure); //根据指定的参数初始化外设 ADCx

4.使能 ADC 并校准。
在设置完了以上信息后, 我们就使能 AD 转换器,执行复位校准和 AD 校准,注意这两步是必须的!不校准将导致结果很不准确。
使能指定的 ADC 的方法是:
ADC_Cmd(ADC1, ENABLE); //使能指定的 ADC1
执行复位校准的方法是:
ADC_ResetCalibration(ADC1);
执行 ADC 校准的方法是:
ADC_StartCalibration(ADC1); //开始指定 ADC1 的校准状态
记住,每次进行校准之后要等待校准结束。 这里是通过获取校准状态来判断是否校准是否结束。下面我们一一列出复位校准和 AD 校准的等待结束方法:
while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束
while(ADC_GetCalibrationStatus(ADC1)); //等待校 AD 准结束
5.读取 ADC 值。
在上面的校准完成之后,ADC 就算准备好了。接下来我们要做的就是设置规则序列 1 里面的通道,采样顺序, 以及通道的采样周期, 然后启动 ADC 转换。在转换结束后,读取 ADC 转换结果值就是了。 这里设置规则序列通道以及采样周期的函数是:
void ADC_RegularChannelConfig(ADC_TypeDef*  ADCx,  uint8_t  ADC_Channel,
uint8_t  Rank,  uint8_t  ADC_SampleTime);
我们这里是规则序列中的第 1 个转换,同时采样周期为 239.5,所以设置为:
ADC_RegularChannelConfig(ADC1, ch, 1,  ADC_SampleTime_239Cycles5 );
软件开启 ADC 转换的方法是:
ADC_SoftwareStartConvCmd(ADC1,  ENABLE);//使能指定的 ADC1 的软件转换启动功能开启转换之后,就可以获取转换 ADC 转换结果数据, 方法是:
ADC_GetConversionValue(ADC1);
同时在 AD 转换中,我们还要根据状态寄存器的标志位来获取 AD 转换的各个状态信息。 库函数获取 AD 转换的状态信息的函数是:
FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx,  uint8_t ADC_FLAG)
比如我们要判断 ADC1d 的转换是否结束,方法是:
while(!ADC_GetFlagStatus(ADC1,  ADC_FLAG_EOC ));//等待转换结束
这里还需要说明一下 ADC 的参考电压,战舰 STM32 开发板使用的是 STM32F103C8T6,该芯片有外部参考电压: Vref-和 Vref+,其中 Vref-必须和 VSSA 连接在一起, 而 Vref+的输入范围为: 2.4~VDDA。如果大家想自己设置其他参考电压,将你的参考电压接在 Vref-和 Vref+上就 OK 了。本章我们的参考电压设置的是 3.3V。
通过以上几个步骤的设置,我们就能正常的使用 STM32 的 ADC1 来执行 AD 转换操作了。
简单总结:
1.RCC配置;
void ADC_RCC_Config(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1|RCC_APB2Periph_USART1, ENABLE);
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);//6分频,72M/6=12M;	
}

2.GPIO配置为GPIO_Mode_AIN;	//模拟输入
void ADC_GPIO_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
}

3. ADC配置;
void ADC_init(void)
{
	ADC_InitTypeDef ADC_InitStructure;
	ADC_DeInit(ADC1);
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
	ADC_InitStructure.ADC_ScanConvMode = ENABLE;
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
	ADC_InitStructure.ADC_NbrOfChannel = 1;
	ADC_Init(ADC1, &ADC_InitStructure);
	ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1,ADC_SampleTime_239Cycles5);//使能或者失能指定的 ADC 规则组通道的间断模式
	ADC_Cmd(ADC1, ENABLE);//使能或者失能指定的 ADC
	 
	ADC_ResetCalibration(ADC1);//重置指定的 ADC 的校准寄存器
	while(ADC_GetResetCalibrationStatus(ADC1));//获取 ADC 重置校准寄存器的状态
	ADC_StartCalibration(ADC1);//开始指定 ADC 的校准状态
	while(ADC_GetCalibrationStatus(ADC1));//获取指定 ADC 的校准程序
	//ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}
4.main函数读取ADC的值
	while(1)
	{
		for(i=0;i<50;i++)//读取50次的AD数值取其平均数较为准确	
		{
			ADC_SoftwareStartConvCmd(ADC1,ENABLE);//使能 ADC 的软件转换启动功能
			while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));//检查制定 ADC 标志位置 1 与否
			Conversion_value+=ADC_GetConversionValue(ADC1);//返回最近一次 ADC1 规则组的转换结果
		
		}
		Conversion_value /=50;//计数50次取平均值;
		printf("%f",Conversion_value*3.3/4096);
	}
}



ADC读取芯片电压
#ifndef _CONFIG_H_
#define _CONFIG_H_

#include 
#include 
#define ADC_conversion
#define Uart1_print
#define Uart1_Txd GPIO_Pin_9
#define Uart1_Rxd	GPIO_Pin_10
void ADC_RCC_Config(void);
void ADC_GPIO_Config(void);
void uart1_Gpio_init(void);
void ADC_init(void);
void uart1_init(void);
void nvic_uart1(void);
int fputc(int ch, FILE *f);
int fgetc(FILE *f);
#endif

#include "Config.h"

#ifdef ADC_conversion
void ADC_RCC_Config(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1|RCC_APB2Periph_USART1, ENABLE);
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);	
}

void ADC_GPIO_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
}

void ADC_init(void)
{
	ADC_InitTypeDef ADC_InitStructure;
	ADC_DeInit(ADC1);
	
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
	ADC_InitStructure.ADC_ScanConvMode = ENABLE;
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
	ADC_InitStructure.ADC_NbrOfChannel = 1;
	ADC_Init(ADC1, &ADC_InitStructure);
	ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1,ADC_SampleTime_239Cycles5);
	ADC_Cmd(ADC1, ENABLE);
	ADC_ResetCalibration(ADC1);
	while(ADC_GetResetCalibrationStatus(ADC1));
	ADC_StartCalibration(ADC1);
	while(ADC_GetCalibrationStatus(ADC1));
	//ADC_SoftwareStartConvCmd(ADC1, ENABLE);
	
	
	
	
}
#endif

#ifdef Uart1_print
void uart1_Gpio_init(void)
{
		GPIO_InitTypeDef GPIO_InitStructure;
		GPIO_InitStructure.GPIO_Pin = Uart1_Txd;
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
		GPIO_Init(GPIOA, &GPIO_InitStructure);

		GPIO_InitStructure.GPIO_Pin = Uart1_Rxd;
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
		GPIO_Init(GPIOA, &GPIO_InitStructure);	


}
/*uart1_init*/
void uart1_init(void)
{
	USART_InitTypeDef USART_InitStructure;
	USART_InitStructure.USART_BaudRate = 9600;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
	USART_Init(USART1, &USART_InitStructure);
	USART_ITConfig(USART1, USART_IT_RXNE,ENABLE);
	USART_ClearFlag(USART1,USART_FLAG_RXNE|USART_FLAG_TC|USART_FLAG_TXE);
	USART_Cmd(USART1, ENABLE);		
}
void nvic_uart1(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;	
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
}
int fputc(int ch, FILE *f)
{
		/* 发送一个字节数据到USART1 */
		USART_SendData(USART1, (uint8_t) ch);
		/* 等待发送完毕 */
		while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);	
		return (ch);
}
/// 重定向c库函数scanf到USART1
int fgetc(FILE *f)
{
		/* 等待串口1输入数据 */
		while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);

		return (int)USART_ReceiveData(USART1);
}
#endif
Main:
#include "Config.h"

int main(void)
{
	int i;
	double Conversion_value;
	ADC_RCC_Config();
  ADC_GPIO_Config();
  uart1_Gpio_init();
  ADC_init();
  uart1_init();
  nvic_uart1();
	
	while(1)
	{
		for(i=0;i<50;i++)//读取50次的AD数值取其平均数较为准确	
		{
			ADC_SoftwareStartConvCmd(ADC1,ENABLE);//使能 ADC 的软件转换启动功能
			while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));//检查制定 ADC 标志位置 1 与否
			Conversion_value+=ADC_GetConversionValue(ADC1);//返回最近一次 ADC1 规则组的转换结果
		
		}
		Conversion_value /=50;//计数50次取平均值;
		printf("%f",Conversion_value*3.3/4096);
	}
}
SPI配置
spi2为主机 spi1为从机:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能GPIOA时钟
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);//使能spi1 
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//使能GPIOB时钟
      RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);//使能spi2
配置spi接口对应的gpio口:
//spi从机    
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;   
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_7;//sck mosi
    GPIO_Init(GPIOA,&GPIO_InitStructure);
    
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;   
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;//miso
    GPIO_Init(GPIOA,&GPIO_InitStructure);
    
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;   
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;//cs
    GPIO_Init(GPIOA,&GPIO_InitStructure);
    //spi主机
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //推挽复用
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_15;//sck mosi
    GPIO_Init(GPIOB,&GPIO_InitStructure);
    
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;   
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;//miso
    GPIO_Init(GPIOB,&GPIO_InitStructure);
    
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;   
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;//cs
    GPIO_Init(GPIOB,&GPIO_InitStructure);

spi口配置:
void SPI1_conf(void)
{
  SPI_InitTypeDef  SPI_InitStructure;
  SPI_Cmd(SPI1, DISABLE);
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;       //
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;//SPI_FirstBit_MSB;
  SPI_InitStructure.SPI_CRCPolynomial = 7;
  SPI_Init(SPI1, &SPI_InitStructure);
   /*Enable SPI1.NSS as a GPIO*/
  //SPI_SSOutputCmd(SPI1, ENABLE);
  SPI_Cmd(SPI1, ENABLE);
  //spi1_cs_low;
}
void SPI2_conf(void)
{
  SPI_InitTypeDef  SPI_InitStructure;
  SPI_Cmd(SPI2, DISABLE);
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;   
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;//SPI_FirstBit_MSB;
  SPI_InitStructure.SPI_CRCPolynomial = 7;
  SPI_Init(SPI2, &SPI_InitStructure);
SPI_Cmd(SPI2, ENABLE);
}

SPI读写数据:
u8 SPIWriteByte(u8 Byte)
{
	while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);		//等待发送区空	  
	SPI_I2S_SendData(SPI2, Byte);	 	            //发送一个byte   
	while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);      //等待接收完一个byte  
	return SPI_I2S_ReceiveData(SPI1);         	    //返回收到的数据			
}

 

你可能感兴趣的:(嵌入式,ARM)