嵌入式学习②——STM32入门初步之LED闪烁

    科技2025-09-18  27

    文章目录

    前言一、STM32实现LED闪烁1.安装mdk5和stm322.使用μVision5创建工程3.STM32编写程序4.编译运行程序 二、C51实现程序1.安装Proteus和Keil42.使用Keil4创建工程3.程序实现4.Proteus仿真 总结


    前言

    为什么使用STM32而不是8051? 是因为51的频率太低,无法满足计算需求?是51的管脚太少,无法满足众多外设的IO? 是51的功耗太大,电池挺不住?是51的功能太弱,而你要使用SPI、I2C、ADC、DMA? 是51的内存太小而你要存储的东西太多?

    当你需要使用STM32某些功能,而51实现不了的时候, 那STM32自然不需要学习,你会直接去寻找STM32某方面的使用方法。 现在我们就来一起从头开始学习STM32的技术


    一、STM32实现LED闪烁

    示例

    1.安装mdk5和stm32

    安装mdk5

    安装STM32

    完成下载

    2.使用μVision5创建工程

    打开软件

    创建工程

    选择单片机

    安装完成

    创建工程如下

    头文件如下

    3.STM32编写程序

    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

    4.编译运行程序

    运行结果如下:


    二、C51实现程序

    1.安装Proteus和Keil4

    软件安装步骤在这里不做赘述

    2.使用Keil4创建工程

    创建工程

    选择单片机

    创建程序如下

    进行Options设置

    <需勾选Create HEX File>

    3.程序实现

    1.main

    #include<reg51.h> #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).

    4.Proteus仿真

    仿真图如下:


    以下是GIF演示 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20201008174047461.gif#pic_center)

    总结

    STM32在使用上比51方便许多 可以看出,若是不配置STM32的PLL,那么相对于51单片机,STM32闪烁LED灯只不过多了一个步骤----配置GPIO口为输出而已。

    Processed: 0.009, SQL: 8