一、led灯
#include "led.h"
void LED_Init(void){ //LED灯的接口初始化
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; //选择端口号
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //选择IO接口工作方式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置IO接口速度(2/10/50MHz)
GPIO_Init(LEDPORT, &GPIO_InitStructure); //#define LEDPORT GPIOC //定义IO接口 abc三组接口
}
二、按键
#include "key.h"
void KEY_Init(void){ //微动开关的接口初始化
GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO的初始化枚举结构
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //选择端口号(0~15或all)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //选择IO接口工作方式 //上拉电阻
// GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置IO接口速度(2/10/50MHz)
GPIO_Init(KEYPORT,&GPIO_InitStructure); //#define KEYPORT GPIOB //定义IO接口组
}
/*
选择IO接口工作方式:
GPIO_Mode_AIN 模拟输入
GPIO_Mode_IN_FLOATING 浮空输入
GPIO_Mode_IPD 下拉输入
GPIO_Mode_IPU 上拉输入
GPIO_Mode_Out_PP 推挽输出
GPIO_Mode_Out_OD 开漏输出
GPIO_Mode_AF_PP 复用推挽输出
GPIO_Mode_AF_OD 复用开漏输出
*/
最好不让用关键变量保存在识别按键的函数中(否则很可能遇到诡异的变量过一会自动清零的现象),而是用一个中间变量保存已按下按键的键值最后再统一进行功能操作
三、OLED(IIC)
1.oled的库函数代码一般直接由卖oled的商家提供,直接调用即可
2.关于取字模可以下载取模软件
3.一个英文字符占88个格子,一个中文字符占816个格子
//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//size:选择字体 12/16/24
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size1)
{
u8 i,m,temp,size2,chr1;
u8 y0=y;
size2=(size1/8+((size1%8)?1:0))*(size1/2); //得到字体一个字符对应点阵集所占的字节数
chr1=chr-' '; //计算偏移后的值
for(i=0;i<size2;i++)
{
if(size1==12)
{temp=asc2_1206[chr1][i];} //调用1206字体
else if(size1==16)
{temp=asc2_1608[chr1][i];} //调用1608字体
else if(size1==24)
{temp=asc2_2412[chr1][i];} //调用2412字体
else return;
for(m=0;m<8;m++) //写入数据
{
if(temp&0x80)OLED_DrawPoint(x,y);
else OLED_ClearPoint(x,y);
temp<<=1;
y++;
if((y-y0)==size1)
{
y=y0;
x++;
break;
}
}
}
}
//显示字符串
//x,y:起点坐标
//size1:字体大小
//*chr:字符串起始地址
void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 size1)
{
while((*chr>=' ')&&(*chr<='~'))//判断是不是非法字符!
{
OLED_ShowChar(x,y,*chr,size1);
x+=size1/2;
if(x>128-size1) //换行
{
x=0;
y+=2;
}
chr++;
}
}
main
OLED_ShowString(40,16,"wecome!",16);
OLED_ShowString(32,32,"temp:",16);OLED_ShowNum(72,32,temp,2,16);OLED_ShowChar(88,32,'C',16);//显示ASCII字符
OLED_ShowString(25,48,"Security:on",16);
OLED_Refresh();//载入!!
四、超声波(UART)
#include "led.h"
五、蓝牙(UART)
u8 USART2_RX_BUF[USART2_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15, 接收完成标志
//bit14, 接收到0x0d
//bit13~0, 接收到的有效字节数目
u16 USART2_RX_STA=0; //接收状态标记
/*
USART2专用的printf函数
*/
void USART2_printf (char *fmt, ...){
char buffer[USART2_REC_LEN+1]; // 数据长度
u8 i = 0;
va_list arg_ptr;
va_start(arg_ptr, fmt);
vsnprintf(buffer, USART2_REC_LEN+1, fmt, arg_ptr);
while ((i < USART2_REC_LEN) && (i < strlen(buffer))){
USART_SendData(USART2, (u8) buffer[i++]);
while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
}
va_end(arg_ptr);
}
void USART2_Init(u32 bound){ //串口1初始化并启动
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); //使能UART2所在GPIOA的时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); //使能串口的RCC时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; //设置USART2的RX接口是PA3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //设置USART2的TX接口是PA2
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure);
//USART2 初始化设置
USART_InitStructure.USART_BaudRate = bound;//一般设置为9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
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_ITConfig(USART2, USART_IT_RXNE, DISABLE);//开启ENABLE/关闭DISABLE中断
USART_Cmd(USART2, ENABLE); //使能串口
//Usart2 NVIC 配置
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
}
void USART2_IRQHandler(void){ //串口2中断服务程序(固定的函数名不能修改)
u8 Res;
//以下是字符串接收到USART2_RX_BUF[]的程序,(USART2_RX_STA&0x3FFF)是数据的长度(不包括回车)
//当(USART2_RX_STA&0xC000)为真时表示数据接收完成,即超级终端里按下回车键。
//在主函数里写判断if(USART2_RX_STA&0xC000),然后读USART2_RX_BUF[]数组,读到0x0d 0x0a即是结束。
//注意在主函数处理完串口数据后,要将USART2_RX_STA清0
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET){ //接收中断(接收到的数据必须是0x0d 0x0a结尾)
Res =USART_ReceiveData(USART2);//(USART1->DR); //读取接收到的数据
printf("%c",Res); //把收到的数据以 a符号变量 发送回电脑
if((USART2_RX_STA&0x8000)==0){//接收未完成
if(USART2_RX_STA&0x4000){//接收到了0x0d
if(Res!=0x0a)USART2_RX_STA=0;//接收错误,重新开始
else USART2_RX_STA|=0x8000; //接收完成了
}else{ //还没收到0X0D
if(Res==0x0d)USART2_RX_STA|=0x4000;
else{
USART2_RX_BUF[USART2_RX_STA&0X3FFF]=Res ; //将收到的数据放入数组
USART2_RX_STA++; //数据长度计数加1
if(USART2_RX_STA>(USART2_REC_LEN-1))USART2_RX_STA=0;//接收数据错误,重新开始接收
}
}
}
}
}
六、舵机(PWM调制)
#include "sg90.h"
//橙色信号线
//红色正极
//棕褐色负极
//具体的周期计算公式为:周期=(arr+1)*(psc+1)/CLK。其中CLK为计数器的时钟频率,
//我的是72MHZ,也就是72000000。最后计算结果单位为秒,结果为0.02s,也就是20ms。
//PWM周期为20ms = (7200*200)/72000000=0.02
//所以TIM_Period = 199,TIM_Prescaler = 7199
//t = 0.5ms——————-舵机会转动 0 °
//t = 1.0ms——————-舵机会转动 45°
//t = 1.5ms——————-舵机会转动 90°
//t = 2.0ms——————-舵机会转动 135°
//t = 2.5ms——————-舵机会转动180°
//PWM占空比是指在一个周期内,信号处于高电平的时间占据整个信号周期的百分比,
//由于PWM周期为20ms,所以(以舵机会转动 45°为例),占空比就应该为1ms/20ms = 5%,
//所以TIM_SetCompare1的 TIMx 捕获比较 1 寄存器值就为200-200*5% = 190
void SG90_pwm_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //声明一个结构体变量,用来初始化GPIO
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//声明一个结构体变量,用来初始化定时器
TIM_OCInitTypeDef TIM_OCInitStructure;//根据TIM_OCInitStruct中指定的参数初始化外设TIMx
/* 开启时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
/* 配置GPIO的模式和IO口 */
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;// PA1
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
GPIO_Init(GPIOA,&GPIO_InitStructure);
//TIM3定时器初始化
TIM_TimeBaseInitStructure.TIM_Period = 199; //PWM 频率=72000/(199+1)=36Khz//设置自动重装载寄存器周期的值
TIM_TimeBaseInitStructure.TIM_Prescaler = 7199;//设置用来作为TIMx时钟频率预分频值
TIM_TimeBaseInitStructure.TIM_ClockDivision = 0;//设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM2, & TIM_TimeBaseInitStructure);
//PWM初始化 //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//PWM输出使能
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;
TIM_OC2Init(TIM2,&TIM_OCInitStructure);
//注意此处初始化时TIM_OC1Init而不是TIM_OCInit,否则会出错。因为固件库的版本不一样。
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);//使能或者失能TIMx在CCR1上的预装载寄存器
TIM_Cmd(TIM2,ENABLE);//使能或者失能TIMx外设
}
七、温度传感器(onewire)
1.ds18b20引脚说明
#include "stm32f10x_conf.h"
#include "delay.h"
#define u8 unsigned char
#define u16 unsigned int
#define Ds18b20 GPIO_Pin_0
#define Ds18b20_PROT GPIOA
#define Ds18b20_LOW GPIO_ResetBits(Ds18b20_PROT,Ds18b20)//引脚置位低电平
#define Ds18b20_HIGH GPIO_SetBits(Ds18b20_PROT,Ds18b20)//引脚置位高电平
void Ds18b20_out_int(u8 cmd)//输入输出状态函数
{
GPIO_InitTypeDef GPIO_InitStructure;
if(cmd)
{
GPIO_InitStructure.GPIO_Pin =Ds18b20;//初始化引脚
GPIO_InitStructure.GPIO_Speed =GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_Out_PP;//输出模式
}
else
{
GPIO_InitStructure.GPIO_Pin =Ds18b20;//初始化引脚
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IPU;//上拉模式模式
}
GPIO_Init(Ds18b20_PROT,&GPIO_InitStructure);
}
u8 Ds18b20_Startup(void)//启动时序
{
u8 data1;
Ds18b20_out_int(1);
Ds18b20_LOW;
delay_us(500);
Ds18b20_HIGH;
delay_us(50);
Ds18b20_out_int(0);
data1=GPIO_ReadInputDataBit(Ds18b20_PROT,Ds18b20);
delay_us(200);
return data1;
}
//data是保留字
void DS18B20_Write_Byte(u8 data1)
{
for(u8 i=0;i<8;i++)
{
Ds18b20_out_int(1);
Ds18b20_LOW;
delay_us(10);
(data1&0x01) ? Ds18b20_HIGH:Ds18b20_LOW;//从高位向低位移动
delay_us(100);
Ds18b20_HIGH;
data1 >>=1;//
}
}
u8 DS18B20_Read_Byte(void)
{
u8 data1=0;
for(u8 i=0;i<8;i++)
{
data1 >>=1;
Ds18b20_out_int(1);//写命令
Ds18b20_LOW;
delay_us(10);
Ds18b20_HIGH;
Ds18b20_out_int(0);//读数据
if(GPIO_ReadInputDataBit(Ds18b20_PROT,Ds18b20)==SET)
{
data1 |=0x80;
}
delay_us(100);
}
return data1;
}
void Ds18b20_Con(void)
{
GPIO_InitTypeDef GPIO_InitStructure;//定义结构体
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//打开a引脚时钟
GPIO_InitStructure.GPIO_Pin =Ds18b20;//初始化引脚
GPIO_InitStructure.GPIO_Speed =GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_Out_PP;
GPIO_Init(Ds18b20_PROT,&GPIO_InitStructure);
}
void Ds18b20_Read_Temp(u16 *data1)
{
u8 ll=0,hh=0;
u16 temp=0;
Ds18b20_Startup();
DS18B20_Write_Byte(0xcc);
DS18B20_Write_Byte(0x44);
delay_ms(750);//12bit精度
Ds18b20_Startup();
DS18B20_Write_Byte(0xcc);
DS18B20_Write_Byte(0xbe);
ll=DS18B20_Read_Byte();
hh=DS18B20_Read_Byte();
temp=(hh<<8 | ll);
*data1=temp;
// if((temp&0xf800) == 0xf800)//负温度处理
// {
// *data1=(((~temp+0x01)*-0.0625)+0.5)*10.0;
// }
// else
// {
// *data1=((temp*0.0625)+0.5)*10.0;
// }
}
八、蜂鸣器
大功率器件不能用单片机io口直接驱动要使用三极管放大电流(s8050)