为什么使用STM32而不是8051? 是因为51的频率太低,无法满足计算需求?是51的管脚太少,无法满足众多外设的IO? 是51的功耗太大,电池挺不住?是51的功能太弱,而你要使用SPI、I2C、ADC、DMA? 是51的内存太小而你要存储的东西太多?
当你需要使用STM32某些功能,而51实现不了的时候, 那STM32自然不需要学习,你会直接去寻找STM32某方面的使用方法。
现在我们就来一起从头开始学习STM32的技术
示例
安装mdk5
1.main.c
int main()
{
LED_Init(); //LED端口及时钟初始化
while(1)
{
led_display(); //led显示
}
}
2.led.c
void LED_Init() //端口初始化
{
GPIO_InitTypeDef GPIO_InitStructure; //声明一个结构体变量,用来初始化GPIO
SystemInit(); //时钟初始化
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
/* 配置GPIO的模式和IO口*/
GPIO_InitStructure.GPIO_Pin=LED; //选择你要设置的IO口
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //设置推挽输出模式
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //设置传输速率
GPIO_Init(GPIOC,&GPIO_InitStructure); /* 初始化GPIO */
}
void led_display()
{
GPIO_SetBits(GPIOC,LED);
delay(6000000); //延时约为1s
GPIO_ResetBits(GPIOC,LED);
delay(6000000);
}
3.led.h
#ifndef _led_H
#define _led_H
#include "stm32f10x.h"
#define LED GPIO_Pin_All //管道宏定义
void LED_Init(void);
void led_display(void);
#endif
运行结果如下:
软件安装步骤在这里不做赘述
1.main
#include
#include"lcd.h"
sbit Ky1=P3^0; //切换
sbit Ky2=P3^1; //数据加1
sbit Ky3=P3^2; //进入/退出设置
sbit Ky4=P3^3; //数据减1
sbit BEEP=P1^5; //接蜂鸣器
sbit LED=P2^0; //接LED
unsigned char Dis_SMG[8];//保存时钟的数据
unsigned char sec,min,hour;
unsigned char year,month,day,week;
unsigned char alarm_hour1=8;
unsigned char alarm_min1=0;
unsigned char alarm_hour2=8;
unsigned char alarm_min2=15;
unsigned char alarm_hour3=9;
unsigned char alarm_min3=0;
unsigned char alarm_hour4=9;
unsigned char alarm_min4=15;
unsigned char alarm_hour5=10;
unsigned char alarm_min5=0;
unsigned char alarm_hour6=10;
unsigned char alarm_min6=15;
unsigned char alarm_hour7=11;
unsigned char alarm_min7=0;
unsigned char alarm_hour8=11;
unsigned char alarm_min8=15;
unsigned char alarm_hour9=12;
unsigned char alarm_min9=0;
unsigned char alarm_hour10=13;
unsigned char alarm_min10=0;
unsigned char alarm_hour11=13;
unsigned char alarm_min11=15;
unsigned char alarm_hour12=14;
unsigned char alarm_min12=0;
unsigned char alarm_hour13=14;
unsigned char alarm_min13=15;
unsigned char alarm_hour14=15;
unsigned char alarm_min14=0;
unsigned char alarm_hour15=15;
unsigned char alarm_min15=15;
unsigned char alarm_hour16=16;
unsigned char alarm_min16=0;
unsigned char alarm_hour17=16;
unsigned char alarm_min17=15;
unsigned char alarm_hour18=17;
unsigned char alarm_min18=0;
unsigned char set_state;
unsigned char set_state2;
unsigned char state=0;
void Dig_Dis();
void Dig_Dis2();
void Dig_Dis3();
void Dig_Dis4();
void Dig_Dis5();
void Delay(unsigned int i);
void Delay1ms(unsigned int c);
void Keycan();
void Keycan2();
void Keycan3();
void Keycan4();
void Keycan5();
void TimerConfiguration();
void Int0Configuration();
void main()
{
LED=1;
LcdInit();
year=20;
month=04;
day=25;
week=2;
sec=50;
min=59;
hour=7;
TimerConfiguration();
Int0Configuration();
LCDWrite_String(4, 1, 8, "Welcome!");
while(1)
{
Keycan();
LCDWrite_String(0, 0, 3, " ");
Dig_Dis();
}
}
void Delay1ms(unsigned int c) //误差 0us
{
unsigned char a,b;
for (; c>0; c--)
{
for(b=199;b>0;b--)
{
for(a=1;a>0;a--);
}
}
}
void TimerConfiguration()
{
TMOD = 0x01; //选择工作方式1
TH0 = 0x3C; //设置初始值
TL0 = 0x0B0;
TH1=(65536-2000)/256;
TL1=(65536-2000)%256;
EA = 1; //打开总中断
ET0 = 1; //打开定时器0中断
TR0 = 1; //启动定时器0
}
void Int0Configuration()
{
//设置INT0
IT0=1;//跳变沿出发方式(下降沿)
EX0=1;//打开INT0的中断允许。
EA=1;//打开总中断
}
void Keycan()
{
unsigned int i;
if(state==1)
{
if(Ky1==0) //检测按键Ky1是否按下
{
Delay1ms(10); //消除抖动
if(Ky1==0)
{
set_state++;
if(set_state>=7)
set_state=0;
}
while((Ky1==0)) //检测按键是否松开
{
Delay1ms(1);
i++;
}
i=0;
}
if(Ky2==0) //检测按键Ky2是否按下
{
Delay1ms(10); //消除抖动
if(Ky2==0)
{
if(set_state==0)
{
sec++;
if(sec>=60)
sec=1;
}
else if(set_state==1)
{
min++;
if(min>=60)
min=1;
}
else if(set_state==2)
{
hour++;
if(hour>=24)
hour=0;
}
else if(set_state==3)
{
day++;
if(day>=32)
day=1;
}
else if(set_state==4)
{
week++;
if(week==8)
week=1;
}
else if(set_state==5)
{
month++;
if(month>=13)
month=1;
}
else
{
year++;
if(year>99)
year=0;
}
}
while((Ky2==0)) //检测按键是否松开
{
Delay1ms(1);
i++;
}
i=0;
}
if(Ky4==0) //检测按键Ky4是否按下
{
Delay1ms(10); //消除抖动
if(Ky4==0)
{
if(set_state==0)
{
sec--;
if(sec<1)
sec=59;
}
else if(set_state==1)
{
min--;
if(min<1)
min=59;
}
else if(set_state==2)
{
hour--;
if(hour==0)
hour=23;
}
else if(set_state==3)
{
day--;
if(day==0)
day=31;
}
else if(set_state==4)
{
week--;
if(week==0)
week=7;
}
else if(set_state==5)
{
month--;
if(month==0)
month=12;
}
else
{
year--;
if(year==0)
year=99;
}
}
while((Ky4==0)) //检测按键是否松开
{
Delay1ms(1);
i++;
}
i=0;
}
}
}
void Dig_Dis()
{
LcdWriteCom(0x80+3);
LcdWriteData('2');
LcdWriteData('0');
LcdWriteData('0'+year/10);
LcdWriteData('0'+year%10);
LcdWriteData('-');
LcdWriteData('0'+month/10);
LcdWriteData('0'+month%10);
LcdWriteData('-');
LcdWriteData('0'+day/10);
LcdWriteData('0'+day%10);
//--显示时钟--//
LcdWriteCom(0xC0+4);
LcdWriteData('0'+hour/10);
LcdWriteData('0'+hour%10);
LcdWriteData(':');
LcdWriteData('0'+min/10);
LcdWriteData('0'+min%10);
LcdWriteData(':');
LcdWriteData('0'+sec/10);
LcdWriteData('0'+sec%10);
LcdWriteCom(0xC0+14);
LcdWriteData('0'+week/10);
LcdWriteData('0'+week%10);
}
void time0() interrupt 1
{
static unsigned int j;
TH0=0Xfc;
TL0=0X18; //1ms
j++;
if(j==1000) //1s
{
j=0;
sec++;
if(sec==60) //秒满60清零
{
sec=0;
min++;
if(min==60) //分满60清零
{
min=0;
hour++;
if(hour==24)
{
hour=0;
day++;
week++;
if(week>7)
{
week=0;
}
if(((month==1)||(month==3)||(month==5)||(month==7)||(month==8)||(month==10)||(month==12))
&&(day==32)
)
{
day=1;
month++;
if(month==13)
{
year++;
month=0;
}
}
if(((month==4)||(month==6)||(month==9)||(month==11))
&&(day==31)
)
{
day=1;
month++;
}
if((((year%4)==0)&&(month==2))
&&(day==30)
)
{
day=1;
month++;
}
if((((year%4)!=0)&&(month==2))
&&(day==29)
)
{
day=1;
month++;
}
}
}
}
if((((hour==alarm_hour1)&&(min==alarm_min1)&&(sec<=10))||
((hour==alarm_hour2)&&(min==alarm_min2)&&(sec<=10))||
((hour==alarm_hour3)&&(min==alarm_min3)&&(sec<=10))||
((hour==alarm_hour4)&&(min==alarm_min4)&&(sec<=10))||
((hour==alarm_hour5)&&(min==alarm_min5)&&(sec<=10))||
((hour==alarm_hour6)&&(min==alarm_min6)&&(sec<=10))||
((hour==alarm_hour7)&&(min==alarm_min7)&&(sec<=10))||
((hour==alarm_hour8)&&(min==alarm_min8)&&(sec<=10))||
((hour==alarm_hour9)&&(min==alarm_min9)&&(sec<=10))||
((hour==alarm_hour10)&&(min==alarm_min10)&&(sec<=10))||
((hour==alarm_hour11)&&(min==alarm_min11)&&(sec<=10))||
((hour==alarm_hour12)&&(min==alarm_min12)&&(sec<=10))||
((hour==alarm_hour13)&&(min==alarm_min13)&&(sec<=10))||
((hour==alarm_hour14)&&(min==alarm_min14)&&(sec<=10))||
((hour==alarm_hour15)&&(min==alarm_min15)&&(sec<=10))||
((hour==alarm_hour16)&&(min==alarm_min16)&&(sec<=10))||
((hour==alarm_hour17)&&(min==alarm_min17)&&(sec<=10))||
((hour==alarm_hour18)&&(min==alarm_min18)&&(sec<=10))
)&&(week<=5))
{
ET1=1;TR1=1; //开启铃声
LED=0;
}
else
{
ET1=0;TR1=0; //关闭铃声
LED=1;
}
}
}
void Beeper() interrupt 3
{
TH1=(65536-2000)/256;
TL1=(65536-2000)%256;
BEEP=!BEEP;
}
void Int0() interrupt 0
{
Delay1ms(10);
if(Ky3==0)
{
state++;
state=state%2;
if(state>0)
{
TR0=0;
}
else
TR0=1;
set_state=0;
set_state2=0;
}
}
2.lch.c
#include"lcd.h"
void LCDWrite_String(uchar x, uchar y, uchar z, uchar *s) //x 0~15 , y 0,1,2,3
{
LCD_set_xy(x,y,z);
while(*s)
{
LcdWriteData(*s);
s++;
}
}
void LCD_set_xy(uchar x,uchar y,uchar z)
{
uchar i;
if(y==0)
{
LcdWriteCom(0x80+x);
for(i=0;i<z;i++)
{
LcdWriteData(' ');
}
LcdWriteCom(0x80+x);
}
if(y==1)
{
LcdWriteCom(0xc0+x);
for(i=0;i<z;i++)
{
LcdWriteData(' ');
}
LcdWriteCom(0xc0+x);
}
if(y==2)
{
LcdWriteCom(0x94+x);
for(i=0;i<z;i++)
{
LcdWriteData(' ');
}
LcdWriteCom(0x94+x);
}
if(y==3)
{
LcdWriteCom(0xd4+x);
for(i=0;i<z;i++)
{
LcdWriteData(' ');
}
LcdWriteCom(0xd4+x);
}
}
void Lcd1602_Delay1ms(uint16 i)
{
while(i--);
}
void LcdWriteCom(uint8 c) //写命令
{
Lcd1602_Delay1ms(1000);
rs=0;
rw=0;
e=0;
P0=c;
e=1;
Lcd1602_Delay1ms(10);
e=0;
/*
P0=c<<4;
e=1;
e=0;*/ //四位的LCD要加上
}
void LcdWriteData(uint8 dat) //写数据
{
Lcd1602_Delay1ms(1000);
rs=1;
rw=0;
e=0;
P0=dat;
e=1;
Lcd1602_Delay1ms(10);
e=0;
/*
P0=dat<<4;
e=1;
e=0;*/ //四位的LCD要加上
rs=0;
}
void LcdInit()
{
Lcd1602_Delay1ms(1000);
/* wrc(0x32);
wrc(0x28);
wrc(0x28); */ //四位的LCD要加上
LcdWriteCom(0x38);
LcdWriteCom(0x38);
LcdWriteCom(0x38);
LcdWriteCom(0x06);
LcdWriteCom(0x0c);
LcdWriteCom(0x01);
}
编译时出现如下警告
linking...
*** WARNING L1: UNRESOLVED EXTERNAL SYMBOL
SYMBOL: ?C_START
MODULE: STARTUP.obj (?C_STARTUP)
*** WARNING L2: REFERENCE MADE TO UNRESOLVED EXTERNAL
SYMBOL: ?C_START
MODULE: STARTUP.obj (?C_STARTUP)
ADDRESS: 080AH
Program Size: data=9.0 xdata=0 code=15
"LED" - 0 Error(s), 2 Warning(s).
仿真图如下:
STM32在使用上比51方便许多
可以看出,若是不配置STM32的PLL,那么相对于51单片机,STM32闪烁LED灯只不过多了一个步骤----配置GPIO口为输出而已。