基于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=50HzTIM_TimeBaseStructure.TIM_Prescaler = 72;//系统默认时钟为72MHz,预分频71+1次,得到TIM3计数时钟为1MHzTIM_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脉冲宽度调制模式1TIM_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<stm32f10x.h>
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();//72mRCC_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;//TXGPIO_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;//RXGPIO_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;   //波特率设置为9600USART_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(溢出时间) = (TIM_Period + 1)(TIM_Prescaler + 1)/Tclk;定时1s
Tout= ((999+1)*(71+1))/Tclk;
1ms = 1000 * 72 / 72000000(hz)
其中:
TIM_Period: 999(1000-1) 定时周期为1000
TIM_Prescaler:71(72-1) 分频系数72
Tclk: TIM1 的输入时钟频率(单位为 khz,72Mhz = 72000000hz)。
Tout: TIM1 溢出时间(单位为 s)。
这里我们设置溢出时间为: 72000/72000000 = 0.001s = 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<config.h>/*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<config.h>
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 ultrasonicvoid 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); //根据指定的参数初始化外设 ADCx4.使能 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);//使能或者失能指定的 ADCADC_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 <stm32f10x.h>
#include <stdio.h>
#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 mosiGPIO_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;//misoGPIO_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;//csGPIO_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 mosiGPIO_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;//misoGPIO_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;//csGPIO_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);               //返回收到的数据
}

基于STM32F103C8T6开发笔记相关推荐

  1. 【嵌入式08.1 - 实验】基于STM32F103C8T6开发板和OLED显示学号姓名+滑频显示

    目录 一.题目要求 二.OLED简介 (一)通信方式 (二)接线方式 (三)应用简介 三.OLED显示姓名学号 (一)环境准备 (二)配套资料包下载 (三)取字模 (四)代码撰写 (五)编译烧录 (六 ...

  2. MyBatis-学习笔记04【04.自定义Mybatis框架基于注解开发】

    Java后端 学习路线 笔记汇总表[黑马程序员] MyBatis-学习笔记01[01.Mybatis课程介绍及环境搭建][day01] MyBatis-学习笔记02[02.Mybatis入门案例] M ...

  3. 树莓派开发笔记(九):基于CSI口的摄像头拍照程序(同样适用USB摄像头)

    若该文为原创文章,未经允许不得转载 原博主博客地址:https://blog.csdn.net/qq21497936 原博主博客导航:https://blog.csdn.net/qq21497936/ ...

  4. 基于Unity的2D小游戏 SpeedDown 开发笔记(学习bilibili@[M_Studio]的教学视频

    基于Unity的2D小游戏 SpeedDown 开发笔记(学习bilibili@M_Studio的教学视频) 主要内容:在Sunnyland游戏的设计基础上,新增了物理组件Joint系列.DrawGi ...

  5. Rock Pi开发笔记(三):Rock Pi 4B plus(基于瑞星微RK3399)板子硬件资源介绍

    若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/123114486 红胖子(红模仿)的博文大全:开发技术集 ...

  6. Rock Pi开发笔记(二):入手Rock Pi 4B plus(基于瑞星微RK3399)板子并制作系统运行

    若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/122942395 红胖子(红模仿)的博文大全:开发技术集 ...

  7. RT-ThreadBearPi 开发笔记 -- 小熊派基于RT-Thread使用ESP8266进行网络连接

    小熊派基于RT-Thread使用ESP8266进行网络连接 物联网的概念和应用场景,最关键最必不可少的一个环节,就是联网.可以说,如果没有可靠的网络连接功能,那这个设备还不算是一个合格的物联网设备. ...

  8. python 知识管理系统_MrDoc: 基于Python开发的Markdown在线文档系统,适合作为个人和小型团队的文档、笔记和知识管理工具...

    MrDoc觅道文档 - 记录文档.汇聚思想 个人和小型团队的笔记.文档.知识管理私有化部署方案 简介 MrDoc 是基于Python开发的在线文档系统,适合作为个人和小型团队的文档.知识和笔记管理工具 ...

  9. STM32CubeMX-HAL库开发笔记(常用语句)-基于Proteus仿真

    STM32CubeMX-HAL库开发笔记 前言 我自己刚刚开始学习STM32时,跟随正点原子课程,一节节课慢慢学,裸机开发可以深入了解和学习到寄存器内部,但是也偏无聊一点.后来,在做项目时,发现很难选 ...

最新文章

  1. 三点弯曲弹性模量怎么计算公式_拉力试验机常用力学计算公式
  2. LabelImg操作及快捷键
  3. 移动开发平台性能比较
  4. XML学习笔记01【xml_基础、xml_约束】
  5. RestTemplate技术预研-认识RestTemplate
  6. java语言怎样判断文件夹_JAVA语言之如何判断文件,判断文件夹是否存在的代码...
  7. svn服务器的搭建过程 主要为服务端
  8. docker1.13.1的安装与卸载及mysql5.5安装实例
  9. java哪个软件编程好学吗_自学编程:Java和C语言相比哪个好?哪个更值得学习?...
  10. Cadence Orcad Capture导出网表的方法图文教程及视频演示
  11. C语言计算圆周率PI的代码
  12. 微软visio2013安装问题及解决过程
  13. Code Smell 检测工具调研
  14. 2017埙箫简谱清单分享(附音频Demo)
  15. UE4遇到的各种奇葩问题
  16. PS 滤镜——(扭曲)逆球面化 (凹陷效果)
  17. springboot项目 o.s.b.d.LoggingFailureAnalysisReporter 错误解决方法
  18. 思考题:现在有4分钟的沙漏和7分钟的沙漏,如何计算出9分钟的时间
  19. .net mvc lambda表达式Contains方法
  20. [HDOJ-4540]威威猫系列故事——打地鼠

热门文章

  1. 166.人工智能眼睛特效
  2. 来日本做码农如何呢(来听听东京大学计算机前辈的回答)
  3. JavaWeb笔试题
  4. 【转】车载导航电子地图走向标准化
  5. Oracle学习-08.09
  6. 状态模式设计程序:游戏中英雄根据不同的体力值可以进行休息、防御、普通攻击、技能攻击。
  7. %2d与%.2d的区别
  8. 小妞会装机 -- 一个装机软件的开发笔记(五)
  9. 从内外参到 Structure From Motion(SFM)
  10. Python脚本统计每个字符的次数/频数(字频统计)