当前位置: 首页 > news >正文

网站ui是平面设计吗/bt磁力天堂torrentkitty

网站ui是平面设计吗,bt磁力天堂torrentkitty,知名品牌形象策划公司,二级分销裂变图文章目录: 一:LED灯操作 1.LED灯的点亮和熄灭 延迟闪烁 main.c led.c led.h BitAction枚举 2.LED呼吸灯(灯的强弱交替变化) main.c delay.c 3.按键控制LED灯 key.h key.c main.c 二:FLASH读写程序(有…

文章目录:

一:LED灯操作 

1.LED灯的点亮和熄灭 延迟闪烁

main.c 

led.c

led.h

BitAction枚举

2.LED呼吸灯(灯的强弱交替变化)

main.c 

delay.c

3.按键控制LED灯

key.h

key.c

main.c 

二:FLASH读写程序(有记忆可以保存断电之前的状态)

flash.h

flash.c

main.c

flash操作注意事项

三:蜂鸣器驱动程序(按键有声音)

buzzer.h

buzzer.c

main.c

四:MIDI音乐播放程序(基于蜂鸣器)

buzzer.c

buzzer.h

main.c

五:USART串口通信驱动程序(串口助手 超级终端)

1.USART发送程序(3种方法)

usart.h

usart.c

main.c

2.USART接收程序(2种方法)

2.1 查询方式接收数据 

main.c

2.2 中断方式接收数据

usart.c

3.USART串口控制程序(双向交互):通过串口助手控制LED灯的开关状态和蜂鸣器、在单片机中按键操作在串口助手中进行显示

main.c

4.超级终端串口远程控制LED程序(命令行操作形式)

usart.h

usart.c        

mian.c

六:RTC实时时钟原理驱动程序

1.基于RTC的LED走时驱动程序(BKP备用寄存器) 

rtc.h

rtc.c

main.c

2.RTC超级终端串口显示日历程序(命令行操作形式)

usart.c

main.c

七:RCC时钟复位和设置程序

rtc.c

mian.c

led.c


 

区别:秒s、毫秒ms、微秒μs、纳秒ns、皮秒ps、飞秒fs每两级之间的换算以及之间的关系_ps和fs区别

区别:千赫kHz、兆赫MHz、吉赫GHz、太赫THz、拍赫PHz、艾赫EHz每两级之间的换算以及之间的关系_太赫兹与ghz

一:LED灯操作 

1.LED灯的点亮和熄灭 延迟闪烁

原理:输出高低电平控制

main.c 

#include "stm32f10x.h"
#include "sys.h"
#include "delay.h"
#include "led.h"int main (void){//主程序RCC_Configuration(); //时钟设置LED_Init();while(1){//方法1:采用枚举(BitAction)(1)    GPIO_WriteBit设置或者清除指定的数据端口位(端口组、端口名、位控制)GPIO_WriteBit(LEDPORT,LED1,(BitAction)(1)); //LED1接口输出高电平1delay_ms(500); //延时0.5秒GPIO_WriteBit(LEDPORT,LED1,(BitAction)(0)); //LED1接口输出低电平0delay_ms(500); //延时0.5秒//方法2:取IO口当前状态            GPIO_ReadOutputDataBit —— 读取端口输出值GPIO_WriteBit(LEDPORT,LED1,(BitAction)(1-GPIO_ReadOutputDataBit(LEDPORT,LED1))); //取反LED1delay_ms(1000); //延时1秒//方法3:直接设置IO口              GPIO_SetBits设置指定的数据端口位(端口组、端口名)GPIO_SetBits(LEDPORT,LED1); //LED灯都为高电平(1)delay_s(1); //延时1秒GPIO_ResetBits(LEDPORT,LED1); //LED灯都为低电平(0)delay_s(1); //延时1秒//方法4:对_ IO 组_ 的数值写入     GPIO_Write向指定GPIO数据端口整组写入数据(端口清零置1)GPIO_Write(LEDPORT,0x0001); //直接数值操作将变量值写入LEDdelay_s(2); //延时1秒GPIO_Write(LEDPORT,0x0000); //直接数值操作将变量值写入LEDdelay_s(2); //延时1秒//方法5:直接控制端口。PB(1)=1;PB1端口直接赋值}
}

led.c

#include "led.h"       //导入自己编写的 led.h的头文件,里面有许多自己宏定义的成员(变量)和函数void LED_Init(void){											 //LED灯的接口初始化GPIO_InitTypeDef  GPIO_InitStructure; 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE);      //高速总线apb2上启动gpio a/b/c       GPIO_InitStructure.GPIO_Pin = LED1 | LED2; 					//选择端口号(0~15或all)              可以使用宏定义名在led.h查看引脚                        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 			//选择IO接口工作方式                   GPIO推挽方式输出   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 			//设置IO接口速度(2/10/50MHz)         只有io被设置为输出时才配置速度GPIO_Init(LEDPORT, &GPIO_InitStructure);		                //将配置的结构体内容写入到ledport-gpiob那一组端口当中	
}

led.h

#ifndef __LED_H 
#define __LED_H	 
#include "sys.h"//#define LED1 PBout(0)// PB0   也可以直接用这   <-容易理解
//#define LED2 PBout(1)// PB1	
#define LEDPORT	GPIOB	//定义IO接口  <- 优点是移植方便 ,越到后面越需要这样编译
#define LED1	GPIO_Pin_0	//定义IO接口
#define LED2	GPIO_Pin_1	//定义IO接口void LED_Init(void);      //LED的初始化函数声明 ,就不用再从.c程序中声明#endif

BitAction枚举

typedef enum
{Bit_REST = 0;Bit_SET; //默认为1这里
}BitAction;

2.LED呼吸灯(灯的强弱交替变化)

原理:调节LED灯点亮和熄灭时间的比例、呼吸灯的速度来控制 

main.c 

#include "stm32f10x.h" //STM32头文件
#include "sys.h"
#include "delay.h"#include "led.h"int main (void){//主程序//定义需要的变量u8 MENU; //菜单模式		8位无符号u16 t,i;	//16位无符号RCC_Configuration(); //时钟设置LED_Init();//led初始化MENU=0;	 //初始菜单状态t=1;   //初始亮状态延时时长//主循环while(1){//菜单0	  根据菜单的值不同运行不同的程序if(MENU==0){for(i=0;i<10;i++)//由于延时时间t从0~500 所以是循环变亮	   i的值可以调节呼吸灯变化的速度{//同一个亮度循环10次GPIO_WriteBit(LEDPORT,LED1,(BitAction)(1));//LED1接口输出高电平1delay_us(t);	GPIO_WriteBit(LEDPORT,LED1,(BitAction)(0));//LED1接口输出高电平1delay_us(501-t);	 //通过将501换成更大的值可以将亮度细分为更多的等级}t++;if(t==500){//由亮变暗MENU=1;}}//菜单1if(MENU==1){for(i=0;i<10;i++)//由于延时时间t从500~0 所以是循环变暗{GPIO_WriteBit(LEDPORT,LED1,(BitAction)(1));//LED1接口输出高电平1delay_us(t);	GPIO_WriteBit(LEDPORT,LED1,(BitAction)(0));//LED1接口输出高电平1delay_us(501-t);	}t--;if(t==1){MENU=0;}}}
}

delay.c

#include "delay.h"#define AHB_INPUT  72                   //请按RCC中设置的AHB时钟频率填写到这里(单位MHz)void delay_us(u32 uS)
{                                       //uS微秒级延时程序(参考值即是延时数,72MHz时最大值233015)	SysTick->LOAD=AHB_INPUT*uS;         //重装计数初值(当主频是72MHz,72次为1微秒)SysTick->VAL=0x00;                  //清空定时器的计数器SysTick->CTRL=0x00000005;           //时钟源HCLK,打开定时器while(!(SysTick->CTRL&0x00010000)); //等待计数到0SysTick->CTRL=0x00000004;           //关闭定时器
}

3.按键控制LED灯

原理:通过读取按键端口输入进行控制

key.h

#ifndef __KEY_H
#define __KEY_H	 
#include "sys.h"//#define KEY1 PAin(0)// PA0
//#define KEY2 PAin(1)// PA1#define KEYPORT	GPIOA	//定义IO接口组
#define KEY1	GPIO_Pin_0	//定义IO接口
#define KEY2	GPIO_Pin_1	//定义IO接口void KEY_Init(void);//声明按键初始化#endif

key.c

#include "key.h"void KEY_Init(void)//微动开关的接口初始化
{ GPIO_InitTypeDef  GPIO_InitStructure; //定义GPIO的初始化枚举结构	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);       GPIO_InitStructure.GPIO_Pin = KEY1 | KEY2; //选择端口号(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);//此时才把io的配置进行初始化!!!		
}

main.c 

#include "stm32f10x.h" //STM32头文件
#include "sys.h"
#include "delay.h"
#include "led.h"#include "key.h" int main (void){//主程序//初始化程序RCC_Configuration(); //时钟设置LED_Init();//LED初始化KEY_Init();//按键初始化//主循环while(1){//GPIO_ReadInputDataBit —— 读取端口输入//示例1:无锁存    按着亮,松开熄灭if(GPIO_ReadInputDataBit(KEYPORT,KEY1)){ //读按键接口的电平GPIO_ResetBits(LEDPORT,LED1); //LED灯都为低电平(0) }else{	GPIO_SetBits(LEDPORT,LED1); //LED灯都为高电平(1) }if(GPIO_ReadInputDataBit(KEYPORT,KEY2)){ //读按键接口的电平GPIO_ResetBits(LEDPORT,LED2); //LED灯都为低电平(0) }else{	GPIO_SetBits(LEDPORT,LED2); //LED灯都为高电平(1) }//示例2:无锁存GPIO_WriteBit(LEDPORT,LED1,(BitAction)(!GPIO_ReadInputDataBit(KEYPORT,KEY1))); //示例3:有锁存    第一次按灯亮,松开还是亮,第二次按熄灭if(!GPIO_ReadInputDataBit(KEYPORT,KEY1)){ //读按键接口的电平delay_ms(20); //延时去抖动if(!GPIO_ReadInputDataBit(KEYPORT,KEY1)){ //读按键接口的电平GPIO_WriteBit(LEDPORT,LED1,(BitAction)(1-GPIO_ReadOutputDataBit(LEDPORT,LED1))); //LED取反while(!GPIO_ReadInputDataBit(KEYPORT,KEY1)); //等待按键松开 }}//示例4:有锁存    按第一次第一个灯亮,按第二次第一个灯熄灭第二个灯亮,按第三次亮灯亮,第四次按同时熄灭if(!GPIO_ReadInputDataBit(KEYPORT,KEY1)){ //读按键接口的电平delay_ms(20); //延时20ms去抖动if(!GPIO_ReadInputDataBit(KEYPORT,KEY1)){ //读按键接口的电平//在2个LED上显示二进制加法a++; //变量加1if(a>3){ //当变量大于3时清0a=0; }GPIO_Write(LEDPORT,a); //直接数值操作将变量值写入LED(LED在GPIOB组的PB0和PB1上)//以a的值赋给端口组,实现 “仅D1亮、仅D2亮、都亮、都灭” 的循环//                          0       1       2     3while(!GPIO_ReadInputDataBit(KEYPORT,KEY1)); //等待按键松开 }}}
}

二:FLASH读写程序(有记忆可以保存断电之前的状态)

原理:通过在指定页擦除和指定地址写入数据进行控制 

如何把存储数据到FLASH中?

在Basic文件夹中——>创建一个FLASH文件夹(flash.c flash.h)注意查看lib文件夹下的flash.c是否存在

flash.h

#ifndef __FLASH_H
#define __FLASH_H 			   
#include "sys.h"#define LEDPORT	GPIOB	//定义IO接口  <- 优点是移植方便 ,越到后面越需要这样编译
#define KEY1	GPIO_Pin_0	//定义IO接口
#define KEY2	GPIO_Pin_1	//定义IO接口void LED_Init(void);      //LED的初始化函数声明 ,就不用再从.c程序中声明
void KEY_Init(void);      //声明按键初始化void FLASH_W(u32 add,u16 dat);
//void FLASH_W(u32 add,u16 dat,u16 dat2);多个情况;若果过多可以使用数组或指针来解决
u16 FLASH_R(u32 add);#endif

flash.c

#include "flash.h"//导入头文件//FLASH写入数据
void FLASH_W(u32 add,u16 dat){ //参数1:32位FLASH地址。参数2:16位数据
//void FLASH_W(u32 add,u16 dat,u16 dat2){//多个情况//	 RCC_HSICmd(ENABLE); //打开HSI时钟FLASH_Unlock();  //解锁FLASH编程擦除控制器FLASH_ClearFlag(FLASH_FLAG_BSY|FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);//清除标志位FLASH_ErasePage(add);               //擦除指定地址页FLASH_ProgramHalfWord(add,dat);     //从指定页的addr地址写入//FLASH_ProgramHalfWord(add+1,dat2);//多个情况(是加上这条)FLASH_ClearFlag(FLASH_FLAG_BSY|FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);//清除标志位FLASH_Lock();    //锁定FLASH编程擦除控制器
}//FLASH读出数据
u16 FLASH_R(u32 add){ //参数1:32位读出FLASH地址。返回值:16位数据u16 a;a = *(u16*)(add);//从指定页的addr地址开始读return a;
}

main.c

#include "stm32f10x.h" //STM32头文件
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "key.h" #include "flash.h" //导入Flash的头文件#define FLASH_START_ADDR  0x0801f000	  //写入的起始地址int main (void){//主程序u16 a; //定义变量//初始化程序RCC_Configuration(); //时钟设置LED_Init();//LED初始化KEY_Init();//按键初始化a = FLASH_R(FLASH_START_ADDR);//从指定页的地址读FLASH//b = FLASH_R(FLASH_START_ADDR);多个情况GPIO_Write(LEDPORT,a); //直接数值操作将变量值写入LED(LED在GPIOB组的PB0和PB1上)//整组写入LED(PB组)//GPIO_Write(LEDPORT,a,b);多个情况//主循环while(1){//示例4:有锁存if(!GPIO_ReadInputDataBit(KEYPORT,KEY1)){ //读按键接口的电平delay_ms(20); //延时20ms去抖动if(!GPIO_ReadInputDataBit(KEYPORT,KEY1)){ //读按键接口的电平//在2个LED上显示二进制加法a++; //变量加1if(a>3){ //当变量大于3时清0a=0; }GPIO_Write(LEDPORT,a); //直接数值操作将变量值写入LED(LED在GPIOB组的PB0和PB1上)FLASH_W(FLASH_START_ADDR,a); //将led的状态值a写入,指定FLASH起始页的地址内//FLASH_W(FLASH_START_ADDR,a,b);多个情况while(!GPIO_ReadInputDataBit(KEYPORT,KEY1)); //等待按键松开 }}}
}

flash操作注意事项

操作一定要先擦后写每页是1024个地址,起始地址Ox08000000擦除操作以页为单位,写操作则必须以16位宽度为单位,允许跨页写入STM32内置FLASH擦或写时,必须打开外部/内部高速振荡器FLASH可多次擦写10万次,不可死循环擦写擦写时要避开用户程序存储区的区域,否则会擦掉用户程序导致错误擦除一页要10ms(对于1k大小的一页),比较慢。而且不能单个字节的擦写

擦除只能以页擦除:临时存储写入地址(空白区域尽量靠后)   不能和    下载用户程序(第0页开始)相互冲突 

三:蜂鸣器驱动程序(按键有声音)

原理:通过延迟时间决定频率震动 和 高低电平循环次数决定持续时长 进行控制 

核心板蜂鸣器电路

在Hardware文件夹中——>创建一个BUZZER文件夹(buzzer.c buzzer.h)

buzzer.h

#ifndef    ——BUZZZER_H
#define    ——BUZZZER_H
#include "sys.h"#define BUZZERPORT	GPIOB	 //定义IO接口     端口组PB5
#define LED1 GPIO_ Pin_o //定义工o接口
#define LED2 GPIO_ Pin_1 //定义工o接口#define BUZZER	GPIO_Pin_5	 //定义IO接口     IO端口void BUZZER_Init(void);   //初始化
void BUZZER_BEEP1(void);  //响一声#endif

buzzer.c

#include "buzzer.h"
#include "delay.h"//蜂鸣器的接口初始化
void BUZZER_Init(void){                                               GPIO_InitTypeDef  GPIO_InitStructure; 	GPIO_InitStructure.GPIO_Pin = BUZZER;            //选择端口号                        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //选择IO接口工作方式       GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//设置IO接口速度(2/10/50MHz)    GPIO_Init(BUZZERPORT, &GPIO_InitStructure);	GPIO_WriteBit(BUZZERPORT,BUZZER,(BitAction)(1)); //蜂鸣器接口输出高电平1	,断开线路,保护蜂鸣器不被损坏或烧坏}//蜂鸣器响一声t
//延迟时间长度决定总周期的长度(修改声音的频率音调)    循环次数i决定蜂鸣器发出(声音持续时间的长度)
void BUZZER_BEEP1(void)                                  //1kHz{                                                    //蜂鸣器响一声u16 i;for(i=0;i<200;i++){GPIO_WriteBit(BUZZERPORT,BUZZER,(BitAction)(0)); //蜂鸣器接口输出0delay_us(500);                               //延时		GPIO_WriteBit(BUZZERPORT,BUZZER,(BitAction)(1)); //蜂鸣器接口输出高电平1delay_us(500);                               //延时		}}

main.c

#include "stm32f10x.h" //STM32头文件
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "flash.h" #include "buzzer.h" 
#define FLASH_START_ADDR  0x0801f000	  //写入的起始地址int main (void){//主程序u8 a; //定义变量//初始化程序RCC_Configuration(); //时钟设置LED_Init();//LED初始化KEY_Init();//按键初始化BUZZER_Init();//蜂鸣器初始化BUZZER_BEEP1();//蜂鸣器响1khza = FLASH_R(FLASH_START_ADDR);//从指定页的地址读FLASH//处理PB1 PB2//因为led是PB0和PB1蜂鸣器的接口,同时是PB5也是。一设置低电平PB端口就全部为0了(默认是PB0 PB1,但这里加入了PB5 就会使蜂鸣器长时间导致发热)//GPIO_ReadOutputData读取整组(LED在GPIOB组)的io口的电平状态	 按位与优先级高//0xfffc&GPIO_ReadOutputData(LEDPORT))高14位保持io口的原来状态,低两位清零//然后与a进行与运算操作变量a的最低两位,再写入PB组的最低两位,其他PB组的其他位不变:将led状态写入,也就是说led在状态写入的时候不会影响其他io电平GPIO_Write(LEDPORT,a|0xfffc&GPIO_ReadOutputData(LEDPORT)); //直接数值操作将变量值写入LED(LED在GPIOB组的PB0和PB1上)//主循环while(1){//示例4:有锁存if(!GPIO_ReadInputDataBit(KEYPORT,KEY1)){ //读按键接口的电平delay_ms(20); //延时20ms去抖动if(!GPIO_ReadInputDataBit(KEYPORT,KEY1)){ //读按键接口的电平//在2个LED上显示二进制加法a++; //变量加1if(a>3){ //当变量大于3时清0a=0; }GPIO_Write(LEDPORT,a|0xfffc&GPIO_ReadOutputData(LEDPORT)); //整组写入不是某个引脚直接数值操作将变量值写入LED(LED在GPIOB组的PB0和PB1上)//a=1是001->pa0=1,a=2是010->pa0=0 pa1=1,a=3是011->pa0=1 pa1=1,a=4是100->pa0=0 pa1=0BUZZER_BEEP1();//蜂鸣器音1FLASH_W(FLASH_START_ADDR,a); //从指定页的地址写入FLASHwhile(!GPIO_ReadInputDataBit(KEYPORT,KEY1)); //等待按键松开 //BUZZER_BEEP2();//蜂鸣器音2}}}
}

四:MIDI音乐播放程序(基于蜂鸣器)

原理:通过改变音调频率 和 时间长度使用蜂鸣器进行控制 

音调与频率的关系 

buzzer.c

uc16 music1[78]={ //音乐的数据表(奇数是音调频率,偶数是时间长度),存于flash中
330,750,
440,375,
494,375,
523,750,
587,375,
659,375,
587,750,
494,375,
392,375,
440,1500,
330,750,
440,375,
494,375,
523,750,
587,375,
659,375,
587,750,
494,375,
392,375,
784,1500,
659,750,
698,375,
784,375,
880,750,
784,375,
698,375,
659,750,
587,750,
659,750,
523,375,
494,375,
440,750,
440,375,
494,375,
523,750,
523,750,
494,750,
392,750,
440,3000
};//MIDI音乐
void MIDI_PLAY(void){     u16 i,e;39个音符循环一次for(i=0;i<39;i++){    //循环不同次数达到让同一个音符播放一段时间长度//music1[i*2]——>0——>330    music1[i*2+1]——>1——>750    (1赫兹=1次/秒) //意思:每秒钟震动330次[Hz],750毫秒[T]震动多少次呢[次数=Hz*T]?for(e=0;e<music1[i*2]*music1[i*2+1]/1000;e++){    //转化为毫秒us 也就是xxx/1000//方波的时间,音效音调高低频率,高电平的延时时间500000us+低电平的延时时间500000us=形成1秒频率周期	GPIO_WriteBit(BUZZERPORT,BUZZER,(BitAction)(0)); //蜂鸣器接口输出0delay_us(500000/music1[i*2]); //延时    1/Hz=sGPIO_WriteBit(BUZZERPORT,BUZZER,(BitAction)(1)); //蜂鸣器接口输出高电平1delay_us(500000/music1[i*2]); //延时	}	}
}

buzzer.h

void MIDI PLAY(void);    //MIDI_PLAY函数声明

main.c

BUZZER_Init ();//蜂鸣器初始化
//BUZZER_BEEP1(0)://蜂鸣器响1khzMIDI_PLAY(); //播放MIDI音乐

五:USART串口通信驱动程序(串口助手 超级终端)

 

DYS串口助手使用:设置自己对应的端口号(自定义)”C0M4“、波特率(自定义)”115200“、发送模式(自定义)”数值“、接收模式(自定义)”数值“最后点击打开端口(自定义)、之后关闭端口(自定义)”数值“:16进制    ”字符“:ASCLL码    发送和接收数据可以相互转换:ASCLL码与进制对应表在Lib文件交接加入:stm32f10x_usart.c串口助手和FlyMcu:如果公用一个端口,那么就不能同时使用

新建文件夹

Basic——>usart——>usart.cusart.h

1.USART发送程序(3种方法)

usart.h

#ifndef __USART_H
#define __USART_H
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "stdio.h"	
#include "sys.h" #define USART_n		USART1  //定义使用printf函数的串口,其他串口要使用USART_printf专用函数发送#define USART1_REC_LEN  			200  	//定义USART1最大接收字节数
#define USART2_REC_LEN  			200  	//定义USART2最大接收字节数
#define USART3_REC_LEN  			200  	//定义USART3最大接收字节数//不使用某个串口时要禁止此串口,以减少编译量
#define EN_USART1 			1		//使能(1)/禁止(0)串口1
#define EN_USART2 			0		//使能(1)/禁止(0)串口2
#define EN_USART3 			0		//使能(1)/禁止(0)串口3extern u8  USART1_RX_BUF[USART1_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 
extern u8  USART2_RX_BUF[USART2_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
extern u8  USART3_RX_BUF[USART3_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符extern u16 USART1_RX_STA;         		//接收状态标记	
extern u16 USART2_RX_STA;         		//接收状态标记	
extern u16 USART3_RX_STA;         		//接收状态标记	//函数声明
void USART1_Init(u32 bound);//串口1初始化并启动
void USART2_Init(u32 bound);//串口2初始化并启动
void USART3_Init(u32 bound);//串口3初始化并启动
void USART1_printf(char* fmt,...); //串口1的专用printf函数
void USART2_printf(char* fmt,...); //串口2的专用printf函数
void USART3_printf(char* fmt,...); //串口3的专用printf函数#endif

usart.c

#include "sys.h"
#include "usart.h"//使UASRT串口可用printf函数发送
//在usart.h文件里可更换使用printf函数的串口号	  
#if 1
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE {int handle; 
}; 
FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
_sys_exit(int x){ x = x; 
} 
//重定义fputc函数 
int fputc(int ch, FILE *f){      while((USART_n->SR&0X40)==0);//循环发送,直到发送完毕   USART_n->DR = (u8) ch;      return ch;
}
#endif /*USART1串口相关程序*/
#if EN_USART1   //USART1使用与屏蔽选择
u8 USART1_RX_BUF[USART1_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.//接收状态//bit15,	接收完成标志//bit14,	接收到0x0d//bit13~0,	接收到的有效字节数目
u16 USART1_RX_STA=0;                  //接收状态标记	  /*USART1专用的printf函数
当同时开启2个以上串口时,printf函数只能用于其中之一,其他串口要自创独立的printf函数
调用方法:USART1_printf("123"); //向USART2发送字符123*/
void USART1_printf (char *fmt, ...)
{ char buffer[USART1_REC_LEN+1];  // 数据长度u8 i = 0;	va_list arg_ptr;va_start(arg_ptr, fmt);  vsnprintf(buffer, USART1_REC_LEN+1, fmt, arg_ptr);while ((i < USART1_REC_LEN) && (i < strlen(buffer))){USART_SendData(USART1, (u8) buffer[i++]);while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET); }va_end(arg_ptr);
}//串口1初始化并启动
void USART1_Init(u32 bound){ //GPIO端口设置GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;	 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	//使能USART1,GPIOA时钟//USART1_TX   PA.9GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出GPIO_Init(GPIOA, &GPIO_InitStructure);  //USART1_RX	  PA.10GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure); //Usart1 NVIC 配置NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;   //抢占优先级3NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器 //USART 初始化设置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(USART1, &USART_InitStructure); //初始化串口USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启ENABLE/关闭DISABLE中断USART_Cmd(USART1, ENABLE);                    //使能串口 
}//串口1的中断处理程序
void USART1_IRQHandler(void)
{                       //串口1中断服务程序(固定的函数名不能修改)	u8 Res;//以下是字符串接收到USART1_RX_BUF[]的程序,(USART1_RX_STA&0x3FFF)是数据的长度(不包括回车)//当(USART1_RX_STA&0xC000)为真时表示数据接收完成,即超级终端里按下回车键。//在主函数里写判断if(USART1_RX_STA&0xC000),然后读USART1_RX_BUF[]数组,读到0x0d 0x0a即是结束。//注意在主函数处理完串口数据后,要将USART1_RX_STA清0if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){                                     //接收中断(接收到的数据必须是0x0d 0x0a结尾)		Res =USART_ReceiveData(USART1);     //(USART1->DR);	//读取接收到的数据printf("%c",Res);                   //把收到的数据以 a符号变量 发送回电脑		if((USART1_RX_STA&0x8000)==0){                                   //接收未完成			if(USART1_RX_STA&0x4000){                                 //接收到了0x0d				if(Res!=0x0a){USART1_RX_STA=0;              //接收错误,重新开始}else{USART1_RX_STA|=0x8000;	    //接收完成了 }}else{                                 //还没收到0X0D					if(Res==0x0d)USART1_RX_STA|=0x4000;else{USART1_RX_BUF[USART1_RX_STA&0X3FFF]=Res ; //将收到的数据放入数组USART1_RX_STA++;	            //数据长度计数加1if(USART1_RX_STA>(USART1_REC_LEN-1)){USART1_RX_STA=0;            //接收数据错误,重新开始接收	  }}		 }}   		 } 
} 
#endif	

main.c

#include "stm32f10x.h" //STM32头文件
#include "sys.h"
#include "delay.h"
#include "usart.h"int main (void)
{                        //主程序u8 a=7,b=8;//初始化程序RCC_Configuration();   //时钟设置USART1_Init(115200);   //串口初始化(参数是波特率)发送和接收波特率必须完全相同//主循环while(1){/* 发送方法1    单个 */USART_SendData(USART1, 0x55);    //发送单个数值(那个端口,发送什么数据)//USART_SendData(USART1, 'U');  while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET); //检查发送中断标志位/* 发送方法2     多个*///	printf("STM32F103 ");          //纯字符串发送数据到串口//	printf("STM32 %d %d ",a,b);    //纯字符串和变量发送数据到串口,a符号变量/* 发送方法3     多个    专用的*///	USART1_printf("STM32 %d %d ",a,b);delay_ms(1000);                    //延时}
}

2.USART接收程序(2种方法)

2.1 查询方式接收数据 

查询要在usart.c的USART初始化设置中关闭中断(当串口接收到数据时才不会跳到中断函数中)ENABLE——>DISABLE

main.c

u8 a;while(){//查询方式接收(发回去,又接收回来),失去实时性if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)!= RESET){    //查询串口待处理标志位    接收数据寄存器非空标志位a =USART_ReceiveData(USART1);                           //读取接收到的数据printf ("%c",a);                                        //把收到的数据发送回电脑}
}

2.2 中断方式接收数据

 中断要在usart.c的USART初始化设置中关闭中断(当串口接收到数据时才不会跳到中断函数中)DISABLE——>ENABLE

usart.c

//中断方式接收程序解读
void USART1_IRQHandler(void){ //串口1中断服务程序(固定的函数名不能修改)	u8 a;if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){  //接收中断(接收到的数据必须是0x0d 0x0a结尾)		Res =USART_ReceiveData(USART1);//(USART1->DR);	//读取接收到的数据printf("%c",a); //把收到的数据以 a符号变量 发送回电脑	}

3.USART串口控制程序(双向交互):通过串口助手控制LED灯的开关状态和蜂鸣器、在单片机中按键操作在串口助手中进行显示

这里需要使用超级终端:并且可以改变终端输出的颜色背景 

输入输出可以一起显示建立连接1.文件——>新建连接——>选择合适的串口(自定义)COM4——>确定2.修改串口(自定义):COM4波特率(自定义):115200编码:GB23123.最后点击确定断开连接串口名字上——>右键——>关闭

main.c

#include "stm32f10x.h" //STM32头文件
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "buzzer.h"
#include "usart.h"
int main (void){//主程序u8 a;//初始化程序RCC_Configuration(); //时钟设置LED_Init();//LED初始化KEY_Init();//按键初始化BUZZER_Init();//蜂鸣器初始化USART1_Init(115200); //串口初始化(参数是波特率)//主循环while(1){//采用查询方式接收   //查询要在usart.c的USART初始化设置中关闭中断(当串口接收到数据时才不会跳到中断函数中)ENABLE——>DISABLE if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE) != RESET){  //查询串口待处理标志位a =USART_ReceiveData(USART1);//读取接收到的数据switch (a){case '0':GPIO_WriteBit(LEDPORT,LED1,(BitAction)(0)); //LED控制printf("%c:LED1 OFF ",a); //不能使用中文break;case '1':GPIO_WriteBit(LEDPORT,LED1,(BitAction)(1)); //LED控制printf("%c:LED1 ON ",a); break;case '2':BUZZER_BEEP1(); //蜂鸣一声printf("%c:BUZZER ",a); //把收到的数据发送回电脑break;default:break;}		  }//按键控制if(!GPIO_ReadInputDataBit(KEYPORT,KEY1)){ //读按键接口的电平delay_ms(20); //延时20ms去抖动if(!GPIO_ReadInputDataBit(KEYPORT,KEY1)){ //读按键接口的电平while(!GPIO_ReadInputDataBit(KEYPORT,KEY1)); //等待按键松开 printf("KEY1 "); printf("KEY1 "); }}		 if(!GPIO_ReadInputDataBit(KEYPORT,KEY2)){ //读按键接口的电平delay_ms(20); //延时20ms去抖动if(!GPIO_ReadInputDataBit(KEYPORT,KEY2)){ //读按键接口的电平while(!GPIO_ReadInputDataBit(KEYPORT,KEY2)); //等待按键松开printf("\O33[1;40;32m KEY2 ");            //改变字体颜色和背景色printf("\O33[1;40;32m KEY2 \O33[om");     //改变字体颜色和背景色,之后又改回来printf("\O33[1;40;32m KEY2 /n/r");        //改变字体颜色和背景色,再次按显示到下一行}}		 //      delay_ms(1000); //延时}
}

4.超级终端串口远程控制LED程序(命令行操作形式)

usart.h

#define USART1_REC_LEN    200;    //定义USART1最大接收字节数
#define USART2_REC_LEN    200;
#define USART3_REC_LEN    200;//全局变量声明
extern u8 USART1_RX_BUF[USART1_REC_LEN];    //接收缓存,最大USART_REC_LEN个字节末字节为换行符
extern u8 USART2_RX_BUF[USART2_REC_LEN];    
extern u8 USART3_RX_BUF[USART3_REC_LEN];   extern u16 USART1_RX_STA;    //接收状态标记
extern u16 USART2_RX_STA;
extern u16 USART3_RX_STA;

usart.c        

u8 USART1_RX_BUF[USART1_REC_LEN];    //接收缓冲,最大USART1_REC_LEN个字节
//全局变量
u16 USART1_RX_STA=0;    //接收状态标记//通过中断函数接收数据
//中断要在usart.c的USART初始化设置中关闭中断(当串口接收到数据时才不会跳到中断函数中)DISABLE——>ENABLE
void USART1_IRQHandler(void)
{ //串口1中断服务程序(固定的函数名不能修改)	u8 Res;//以下是字符串接收到USART_RX_BUF[]的程序,(USART_RX_STA&0x3FFF)是数据的长度(不包括回车)//当(USART_RX_STA&0xC000)为真时表示数据接收完成,即超级终端里按下回车键。//在主函数里写判断if(USART_RX_STA&0xC000),然后读USART_RX_BUF[]数组,读到0x0d 0x0a即是结束//注意在主函数处理完串口数据后,要将USART_RX_STA清0//多字符指令接收if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {    //接收中断(接收到的数据必须是0x0d回车符 0x0a结尾)		Res =USART_ReceiveData(USART1);//(USART1->DR);	//读取接收到的数据printf("%c",Res); //把收到的数据以 a符号变量 发送回电脑//USART1_RX_STA初始值为0	if((USART1_RX_STA&0x8000)==0) {    //接收未完成	接收状态标记	最高位第1位	    定义了初始为0if(USART1_RX_STA&0x4000){        //接收到了0x0d		        最高位第2位//判断是不是0x0a /r			if(Res!=0x0a){USART1_RX_STA=0;}             //接收错误,重新开始,状态位清零else{USART1_RX_STA|=0x8000;}       //接收完成了,是0x0a,那么把最高位状态位置1【11】}else{//还没收到0X0D     /n按键	    回车键=ox0D+0x0a组合=/n/r	//是回车,第二位置1			if(Res==0x0d){USART1_RX_STA|=0x4000;}    //0100 0 0 0     最高位第2位 置1【11】//不是回车去除掉最高两位else{USART1_RX_BUF[USART1_RX_STA&0X3FFF]=Res ; //将收到的数据放入数组    最高位的2位去除掉	    0011FFFUSART1_RX_STA++;	//数据长度计数加1if(USART1_RX_STA>(USART1_REC_LEN-1))     //读到的值超过数组的最大值{USART1_RX_STA=0;}                   //接收数据错误,重新开始接收,状态标志清零	            }		 }}}
}

mian.c

#include "stm32f10x.h" //STM32头文件
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "buzzer.h"
#include "usart.h"int main (void){//主程序RCC_Configuration();LED_Init();//LED初始化KEY_Init();//按键初始化BUZZER_Init();//蜂鸣器初始化USART1_Init(115200); //串口初始化,参数中写波特率USART1_RX_STA=0xC000; //初始值设为有回车的状态,即显示一次欢迎词while(1){//判断最高位和最高位的第二位 是不是1    1100 0 0 0if(USART1_RX_STA&0xC000){ //如果标志位是0xC000表示收到数据串完成,可以处理。//判断数据是0个,从而看是不是按了回车    去掉状态变量最高两位0011FFF(表示没有输入任何字符)if((USART1_RX_STA&0x3FFF)==0){ //单独的回车键再显示一次欢迎词printf("\033[1;47;33m\r\n"); //设置颜色(参考超级终端使用)printf(" 1y--开LED1灯      1n--关LED1灯 \r\n");printf(" 2y--开LED2灯      2n--关LED2灯 \r\n");printf(" 请输入控制指令,按回车键执行! \033[0m\r\n");}else if((USART1_RX_STA&0x3FFF)==2 && USART1_RX_BUF[0]=='1' && USART1_RX_BUF[1]=='y'){ //判断数据是不是2个,第一个数据是不是“1”,第二个是不是“y”GPIO_SetBits(LEDPORT,LED1); //LED灯都为高电平(1)printf("1y -- LED1灯已经点亮!\r\n");}else if((USART1_RX_STA&0x3FFF)==2 && USART1_RX_BUF[0]=='1' && USART1_RX_BUF[1]=='n'){GPIO_ResetBits(LEDPORT,LED1); LED灯都为低电平(0)printf("1n -- LED1灯已经熄灭!\r\n");}else if((USART1_RX_STA&0x3FFF)==2 && USART1_RX_BUF[0]=='2' && USART1_RX_BUF[1]=='y'){GPIO_SetBits(LEDPORT,LED2); //LED灯都为高电平(1)printf("2y -- LED2灯已经点亮!\r\n");}else if((USART1_RX_STA&0x3FFF)==2 && USART1_RX_BUF[0]=='2' && USART1_RX_BUF[1]=='n'){GPIO_ResetBits(LEDPORT,LED2); LED灯都为低电平(0)printf("2n -- LED2灯已经熄灭!\r\n");}else{ //如果以上都不是,即是错误的指令。printf("指令错误!\r\n"); }USART1_RX_STA=0; //将串口数据标志位清0}}
}

六:RTC实时时钟原理驱动程序

 

1.基于RTC的LED走时驱动程序(BKP备用寄存器) 

新建文件夹

Basic——>rtc文件夹——>rtc.c rtc.h在Lib文件夹下 添加:stm32f10x_rtc.c

LED1代表秒:奇数点亮,偶数熄灭;LED2代表分钟:奇数点亮,偶数熄灭

rtc.h

#ifndef __RTC_H
#define __RTC_H	 
#include "sys.h" //全局变量的声明,在rtc.c文件中定义
//以下2条是使用extern语句声明全局变量,时钟计算出的年月日时分秒
//注意:这里不能给变量赋值extern u16 ryear;
extern u8 rmon,rday,rhour,rmin,rsec,rweek;    //年月日时分秒//函数声明
u8 RTC_Get(void);                                               //读出当前时间值
u8 RTC_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec);    //写入当前时间值void RTC_First_Config(void);                                    //首次启用RTC的设置(全部初始化)
void RTC_Config(void);                                          //实时时钟初始化(部分初始化)//下面包含在时间读写函数里面,不需要单独调用
u8 Is_Leap_Year(u16 year);                                      //判断是否是闰年函数                    
u8 RTC_Get_Week(u16 year,u8 month,u8 day);                      //按年月日计算星期几#endif

rtc.c

#include "sys.h"
#include "rtc.h"//以下2条全局变量--用于RTC时间的读取
u16 ryear; //4位年
u8 rmon,rday,rhour,rmin,rsec,rweek;//2位月日时分秒周//首次启用RTC的初始化设置
void RTC_First_Config(void){ RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);//启用PWR电源管理部分和BKP备用寄存器的时钟(from APB1)PWR_BackupAccessCmd(ENABLE);//后备域解锁    使能或者失能RTC和后备寄存器访问BKP_DeInit();//备份寄存器模块复位            将外设BKP的全部寄存器重设为缺省值RCC_LSEConfig(RCC_LSE_ON);//外部32.768KHZ晶振开启   while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);//等待稳定    RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);//RTC时钟源配置成LSE(外部低速晶振32.768KHZ)    RCC_RTCCLKCmd(ENABLE);//RTC开启    RTC_WaitForSynchro();//开启后需要等待APB1时钟与RTC时钟同步,才能读写寄存器    RTC_WaitForLastTask();//读写寄存器前,要确定上一个操作已经结束RTC_SetPrescaler(32767);//设置RTC分频器,使RTC时钟为1Hz,RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1)   RTC_WaitForLastTask();//等待寄存器写入完成	//当不使用RTC秒中断,可以屏蔽下面2条
//    RTC_ITConfig(RTC_IT_SEC, ENABLE);//使能秒中断   
//    RTC_WaitForLastTask();//等待写入完成
}//实时时钟一般初始化设置
void RTC_Config(void){ //在BKP的后备寄存器1中,存了一个特殊字符0xA5A5//第一次上电或后备电源掉电后,该寄存器数据丢失,表明RTC数据丢失,需要重新配置if (BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5){//判断寄存数据是否丢失  从指定的后备寄存器中读取数据       RTC_First_Config();//重新配置RTC        BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);//配置完成后,向后备寄存器中写特殊字符0xA5A5}else{//若后备寄存器没有掉电,则无需重新配置RTC//这里我们可以利用RCC_GetFlagStatus()函数查看本次复位类型if (RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET){//这是上电复位}else if (RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET){//这是外部RST管脚复位}       RCC_ClearFlag();//清除RCC中复位标志//虽然RTC模块不需要重新配置,且掉电后依靠后备电池依然运行//但是每次上电后,还是要使能RTCCLKRCC_RTCCLKCmd(ENABLE);//使能RTCCLK        RTC_WaitForSynchro();//等待RTC时钟与APB1时钟同步//当不使用RTC秒中断,可以屏蔽下面2条
//        RTC_ITConfig(RTC_IT_SEC, ENABLE);//使能秒中断        
//        RTC_WaitForLastTask();//等待操作完成}//是否启用rtc的输出功能,一般情况下不使用#ifdef RTCClockOutput_Enable   RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);PWR_BackupAccessCmd(ENABLE);   BKP_TamperPinCmd(DISABLE);   BKP_RTCOutputConfig(BKP_RTCOutputSource_CalibClock);#endif
}//RTC时钟1秒触发中断函数(名称固定不可修改)
void RTC_IRQHandler(void){if (RTC_GetITStatus(RTC_IT_SEC) != RESET){//写入自己的程序}RTC_ClearITPendingBit(RTC_IT_SEC); RTC_WaitForLastTask();
}//闹钟中断处理(启用时必须调高其优先级)
void RTCAlarm_IRQHandler(void){if(RTC_GetITStatus(RTC_IT_ALR) != RESET){}RTC_ClearITPendingBit(RTC_IT_ALR);RTC_WaitForLastTask();
}//时间读写计算
//判断是否是闰年函数
//月份   1  2  3  4  5  6  7  8  9  10 11 12
//闰年   31 29 31 30 31 30 31 31 30 31 30 31
//非闰年 31 28 31 30 31 30 31 31 30 31 30 31
//输入:年份
//输出:该年份是不是闰年.1,是.0,不是
u8 Is_Leap_Year(u16 year){                    if(year%4==0){ //必须能被4整除if(year%100==0){		if(year%400==0)return 1;//如果以00结尾,还要能被400整除          else return 0;  }else return 1;  }else return 0;
}                           
//设置时钟
//把输入的时钟转换为秒钟
//以1970年1月1日为基准
//1970~2099年为合法年份//月份数据表                                                                       
u8 const table_week[12]={0,3,3,6,1,4,6,2,5,0,3,5}; //月修正数据表  
const u8 mon_table[12]={31,28,31,30,31,30,31,31,30,31,30,31};//平年的月份日期表//写入时间
u8 RTC_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec){ //写入当前时间(1970~2099年有效),u16 t;u32 seccount=0;if(syear<2000||syear>2099)return 1;//syear范围1970-2099,此处设置范围为2000-2099       for(t=1970;t<syear;t++){ //把所有年份的秒钟相加if(Is_Leap_Year(t))seccount+=31622400;//闰年的秒钟数else seccount+=31536000;                    //平年的秒钟数}smon-=1;for(t=0;t<smon;t++){         //把前面月份的秒钟数相加seccount+=(u32)mon_table[t]*86400;//月份秒钟数相加if(Is_Leap_Year(syear)&&t==1)seccount+=86400;//闰年2月份增加一天的秒钟数        }seccount+=(u32)(sday-1)*86400;//把前面日期的秒钟数相加seccount+=(u32)hour*3600;//小时秒钟数seccount+=(u32)min*60;      //分钟秒钟数seccount+=sec;//最后的秒钟加上去RTC_First_Config(); //重新初始化时钟BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);//配置完成后,向后备寄存器中写特殊字符0xA5A5RTC_SetCounter(seccount);//把换算好的计数器值写入RTC_WaitForLastTask(); //等待写入完成return 0; //返回值:0,成功;其他:错误代码.    
}//读出时间
u8 RTC_Get(void){//读出当前时间值 //返回值:0,成功;其他:错误代码.static u16 daycnt=0;u32 timecount=0;u32 temp=0;u16 temp1=0;timecount=RTC_GetCounter();		temp=timecount/86400;   //得到天数(秒钟数对应的)if(daycnt!=temp){//超过一天了daycnt=temp;temp1=1970;  //从1970年开始while(temp>=365){if(Is_Leap_Year(temp1)){//是闰年if(temp>=366)temp-=366;//闰年的秒钟数else {temp1++;break;} }else temp-=365;       //平年temp1++; }  ryear=temp1;//得到年份temp1=0;while(temp>=28){//超过了一个月if(Is_Leap_Year(ryear)&&temp1==1){//当年是不是闰年/2月份if(temp>=29)temp-=29;//闰年的秒钟数else break;}else{if(temp>=mon_table[temp1])temp-=mon_table[temp1];//平年else break;}temp1++; }rmon=temp1+1;//得到月份rday=temp+1;  //得到日期}temp=timecount%86400;     //得到秒钟数      rhour=temp/3600;     //小时rmin=(temp%3600)/60; //分钟     rsec=(temp%3600)%60; //秒钟rweek=RTC_Get_Week(ryear,rmon,rday);//获取星期  return 0;
}    //获取星期几
//按年月日计算星期(只允许1901-2099年)//已由RTC_Get调用    
u8 RTC_Get_Week(u16 year,u8 month,u8 day){ u16 temp2;u8 yearH,yearL;yearH=year/100;     yearL=year%100;// 如果为21世纪,年份数加100 if (yearH>19)yearL+=100;// 所过闰年数只算1900年之后的 temp2=yearL+yearL/4;temp2=temp2%7;temp2=temp2+day+table_week[month-1];if (yearL%4==0&&month<3)temp2--;return(temp2%7); //返回星期值
}

main.c

#include "stm32f10x.h" //STM32头文件
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "buzzer.h"
#include "usart.h"#include "rtc.h"int main (void){//主程序RCC_Configuration(); //系统时钟初始化RTC_Config(); //实时时钟初始化LED_Init();//LED初始化KEY_Init();//按键初始化BUZZER_Init();//蜂鸣器初始化USART1_Init(115200); //串口初始化,参数中写波特率USART1_RX_STA=0xC000; //初始值设为有回车的状态,即显示一次欢迎词while(1){if(RTC_Get()==0){ //读出时间值,同时判断返回值是不是0,非0时读取的值是错误的。	GPIO_WriteBit(LEDPORT,LED1,(BitAction)(rsec%2)); //LED1接口    读出秒数,取余表示led的状态    GPIO_WriteBit(LEDPORT,LED2,(BitAction)(rmin%2)); //LED2接口    读出分钟数,取余表示led的状态    }}
}

2.RTC超级终端串口显示日历程序(命令行操作形式)

在超级终端按回车键,之后显示更新时间 初始化时钟 输入设置时间

usart.c

//开启中断
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启ENABLE/关闭DISABLE中断

main.c

#include "stm32f10x.h"    //STM32头文件
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "buzzer.h"
#include "usart.h"
#include "rtc.h"int main (void){//主程序u8 bya;RCC_Configuration(); //系统时钟初始化RTC_Config(); //实时时钟初始化LED_Init();//LED初始化KEY_Init();//按键初始化BUZZER_Init();//蜂鸣器初始化USART1_Init(115200); //串口初始化,参数中写波特率USART1_RX_STA=0xC000; //初始值设为有回车的状态,即显示一次欢迎词while(1){if(USART1_RX_STA&0xC000){ //如果标志位是0xC000表示收到数据串完成,可以处理。if((USART1_RX_STA&0x3FFF)==0){ //单独的回车键再显示一次欢迎词if(RTC_Get()==0){ //读出时间值,同时判断返回值是不是0,非0时读取的值是错误的。printf(" 洋桃开发板STM32实时时钟测试程序   \r\n");printf(" 现在实时时间:%d-%d-%d %d:%d:%d  ",ryear,rmon,rday,rhour,rmin,rsec);//显示日期时间//分钟和秒钟的各位与十位分开:单独显示  printf(" 现在实时时间:%d-%d-%d %d:%d%d:%d%d  ",ryear,rmon,rday,rhour,rmin/10,rmin%10,rsec/10,rsec%10);//显示日期时间          if(rweek==0)printf("星期日   \r\n");//rweek值为0时表示星期日if(rweek==1)printf("星期一   \r\n");if(rweek==2)printf("星期二   \r\n");if(rweek==3)printf("星期三   \r\n");if(rweek==4)printf("星期四   \r\n");if(rweek==5)printf("星期五   \r\n");if(rweek==6)printf("星期六   \r\n");printf(" 单按回车键更新时间。输入字母C初始化时钟 \r\n");printf(" 请输入设置时间,格式20170806120000,按回车键确定! \r\n");}else{printf("读取失败!\r\n");}}else if((USART1_RX_STA&0x3FFF)==1){ //判断数据是不是2个if(USART1_RX_BUF[0]=='c' || USART1_RX_BUF[0]=='C'){RTC_First_Config(); //键盘输入c或C,初始化时钟BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);//配置完成后,向后备寄存器中写特殊字符0xA5A5printf("初始化成功!      \r\n");//显示初始化成功}else{printf("指令错误!          \r\n"); //显示指令错误!} }else if((USART1_RX_STA&0x3FFF)==14){ //判断数据是不是14个//将超级终端发过来的数据换算并写入RTC    ox30是偏移量=0(实现1~9的对应)    ryear = (USART1_RX_BUF[0]-0x30)*1000+(USART1_RX_BUF[1]-0x30)*100+(USART1_RX_BUF[2]-0x30)*10+USART1_RX_BUF[3]-0x30;rmon = (USART1_RX_BUF[4]-0x30)*10+USART1_RX_BUF[5]-0x30;//串口发来的是字符,减0x30后才能得到十进制0~9的数据rday = (USART1_RX_BUF[6]-0x30)*10+USART1_RX_BUF[7]-0x30;rhour = (USART1_RX_BUF[8]-0x30)*10+USART1_RX_BUF[9]-0x30;rmin = (USART1_RX_BUF[10]-0x30)*10+USART1_RX_BUF[11]-0x30;rsec = (USART1_RX_BUF[12]-0x30)*10+USART1_RX_BUF[13]-0x30;bya=RTC_Set(ryear,rmon,rday,rhour,rmin,rsec); //将数据写入RTC计算器的程序if(bya==0)printf("写入成功!      \r\n");//显示写入成功 else printf("写入失败!       \r\n"); //显示写入失败}else{ //如果以上都不是,即是错误的指令。printf("指令错误!          \r\n"); //如果不是以上正确的操作,显示指令错误!}USART1_RX_STA=0; //将串口数据标志位清0}}
}

七:RCC时钟复位和设置程序

左边——产生阻频;左边——分配阻频

rtc.c

//RCC时钟的设置  
void RCC_Configuration(void){ ErrorStatus HSEStartUpStatus;       //枚举定义RCC_DeInit();              /* RCC system reset(for debug purpose) RCC寄存器恢复初始化值*/   RCC_HSEConfig(RCC_HSE_ON); /* Enable HSE 使能外部高速晶振*/   HSEStartUpStatus = RCC_WaitForHSEStartUp(); /* Wait till HSE is ready 等待外部高速晶振使能完成*/   if(HSEStartUpStatus == SUCCESS){   /*设置PLL时钟源及倍频系数    那种时钟源那种方式输入 倍频系数*/   RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); //RCC_PLLMul_x(枚举2~16)是倍频值。当HSE=8MHZ,RCC_PLLMul_9时PLLCLK=72MHZ   /*设置AHB时钟(HCLK)*/   RCC_HCLKConfig(RCC_SYSCLK_Div1); //RCC_SYSCLK_Div1——AHB时钟 = 系统时钟(SYSCLK) = 72MHZ(外部晶振8HMZ)   /*注意此处的设置,如果使用SYSTICK做延时程序,此时SYSTICK(Cortex System timer)=HCLK/8=9MHZ*/   RCC_PCLK1Config(RCC_HCLK_Div2); //设置低速AHB时钟(PCLK1),RCC_HCLK_Div2——APB1时钟 = HCLK/2 = 36MHZ(外部晶振8HMZ)   RCC_PCLK2Config(RCC_HCLK_Div1); //设置高速AHB时钟(PCLK2),RCC_HCLK_Div1——APB2时钟 = HCLK = 72MHZ(外部晶振8HMZ)   /*注:AHB主要负责外部存储器时钟。APB2负责AD,I/O,高级TIM,串口1。APB1负责DA,USB,SPI,I2C,CAN,串口2,3,4,5,普通TIM */  FLASH_SetLatency(FLASH_Latency_2); //设置FLASH存储器延时时钟周期数   /*FLASH时序延迟几个周期,等待总线同步操作。   推荐按照单片机系统运行频率:0—24MHz时,取Latency_0;   24—48MHz时,取Latency_1;   48~72MHz时,取Latency_2*/   FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //选择FLASH预取指缓存的模式,预取指缓存使能   RCC_PLLCmd(ENABLE);	//使能PLLwhile(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); //等待PLL输出稳定   RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //选择SYSCLK时钟源为PLLwhile(RCC_GetSYSCLKSource() != 0x08); //等待PLL成为SYSCLK时钟源   }  //开启需要使用的外设时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA |  RCC_APB2Periph_GPIOB |RCC_APB2Periph_GPIOC| RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE, ENABLE); //APB2外设时钟使能      RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); //APB1外设时钟使能  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);   RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);   	 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);  }

mian.c

RCC_Configuration(); //系统时钟初始化

led.c

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE);      //高速总线apb2上启动gpio a/b/c  

相关文章:

STM32基础入门学习笔记:核心板 电路原理与驱动编程

文章目录&#xff1a; 一&#xff1a;LED灯操作 1.LED灯的点亮和熄灭 延迟闪烁 main.c led.c led.h BitAction枚举 2.LED呼吸灯&#xff08;灯的强弱交替变化&#xff09; main.c delay.c 3.按键控制LED灯 key.h key.c main.c 二&#xff1a;FLASH读写程序(有…...

最后一次模拟考试题解

哦我想这不用看都知道是为了水任务 T1 黑白染色 其实这题有原 什么手写体 md (指 markdown) 分析 首先这题如果你题目没看错的话 ,会发现其实他是 n m n \times m nm 让你求 n n n \times n nn 的区域内的点&#xff08;不会只有我一个人题目看错了罢 然后我们会发现…...

Mac 创建和删除 Automator 工作流程,设置 Terminal 快捷键

1. 创建 Automator 流程 本文以创建一个快捷键启动 Terminal 的自动操作为示例。 点击打开 自动操作&#xff1b; 点击 新建文稿 点击 快速操作 选择 运行 AppleScript 填入以下内容 保存名为 “Open Terminal” 打开 设置 > 键盘&#xff0c;选择 键盘快捷键 以此选择 服…...

2023华为OD机试真题B卷 Java 实现【最长的元音串】

前言 本题使用Java解答,如果需要Python代码,链接 题目 给定一个只由英文字母(a-z, A-Z)组成的字符串,找出其中最长的只包含元音字母(a, e, i, o, u, A, E, I, O, U)的子串,并返回其长度。如果不存在元音子串,则返回0。 输入: 一个由英文字母组成的字符串,长度大…...

网络防御之传输安全

1.什么是数据认证&#xff0c;有什么作用&#xff0c;有哪些实现的技术手段? 数据认证是一种权威的电子文档 作用&#xff1a;它能保证数据的完整性、可靠性、真实性 技术手段有数字签名、加密算法、哈希函数等 2.什么是身份认证&#xff0c;有什么作用&#xff0c;有哪些…...

【css】组合器

组合器是解释选择器之间关系的某种机制。在简单选择器器之间&#xff0c;可以包含一个组合器&#xff0c;从而实现简单选择器难以达到的效果。 CSS 中有四种组合器&#xff1a; 后代选择器 (空格)&#xff1a;匹配属于指定元素后代的所有元素&#xff0c;示例&#xff1a;div …...

HTTPS、TLS加密传输

HTTPS、TLS加密传输 HTTPS、TLS加密传输1、HTTPS&#xff08;HyperText Transfer Protocol Secure&#xff09;2、TLS HTTPS、TLS加密传输 1、HTTPS&#xff08;HyperText Transfer Protocol Secure&#xff09; HTTPS&#xff08;HyperText Transfer Protocol Secure&#x…...

docker frp 搭建 http + stcp 代理

所需服务器 2台 一台具有国外公网ip 一台具有国内 ip 内网外网都可以 外公网ip服务器配置如下 cat docker-compose.yamlversion: "2" services:frps:image: alpine:latesthostname: frpsrestart: alwayscontainer_name: frpsprivileged: trueuser: rootcommand: […...

项目出bug,找不到bug,如何拉回之前的版本

1.用gitee如何拉取代码 本文为转载于「闪耀太阳a」的原创文章原文链接&#xff1a;https://blog.csdn.net/Gufang617/article/details/119929145 怎么从gitee上拉取代码 1.首先找到gitee上想要拉取得代码URL地址 点击复制这里的https地址 1 ps:&#xff08;另外一种方法&…...

vue-cli

vue-cli脚手架 案例一&#xff1a; 案例二&#xff1a; 案例三&#xff1a; ​ 一、脚手架简介 Vue脚手架是Vue官方提供的标准化开发工具&#xff08;开发平台&#xff09;&#xff0c;它提供命令行和UI界面&#xff0c;方便创建vue工程、配置第三方依赖、编译vue工程 1. …...

android获取屏幕分辨率的正确方法;获取到分辨率(垂直方向像素)的不正确

我通过下面的方法去获取屏幕分辨率的&#xff0c;但获取到的分辨率有时会不准确。原因是此方法有时候会忽略一些布局或控件的高度&#xff0c;从而得不到正确的高度。 public static String getDeviceResolution(Context context){//从系统服务中获取窗口管理器WindowManager w…...

机器学习笔记之优化算法(八)简单认识Wolfe Condition的收敛性证明

机器学习笔记之优化算法——简单认识Wolfe Condition收敛性证明 引言回顾&#xff1a; Wolfe \text{Wolfe} Wolfe准则准备工作推导条件介绍推导结论介绍 关于 Wolfe \text{Wolfe} Wolfe准则收敛性证明的推导过程 引言 上一节介绍了非精确搜索方法—— Wolfe \text{Wolfe} Wolf…...

通过win+r安装jupyter报错

通过pip install jupyter安装jupyter报错处理办法 1、python 更新到最新版&#xff0c;最好多执行几次后在安装jupyter python.exe -m pip install --upgrade pip 2、通过镜像安装 pip install jupyter --force-reinstall pip -i http://pypi.douban.com/simple/ --trusted-h…...

C#声明一个带返回值的委托

1、声明 public delegate string TestDel(string str); 2、使用 TestDel t; t (string str) > str; t (string str) > str "1"; t (string str) > str "2"; t (string str) > str "3"; Console.WriteLine(t ("hhhh&qu…...

Flutter 自定义view

带进度动画的圆环。没gif&#xff0c;效果大家自行脑补。 继承CustomPainter&#xff0c;paint()方法中拿到canvas&#xff0c;绘制API和android差不多。 import package:flutter/material.dart;class ProgressRingPainter extends CustomPainter {double strokeWidth 20;Col…...

Ubuntu新装系统报错:sudo: vim:找不到命令

问题&#xff1a; 新安装的老版本Ubuntu系统&#xff0c;发现在使用vim命令的时候报错&#xff1a; sudo&#xff1a;vim&#xff1a;找不到命令 解决办法 这是因为没有安装vim&#xff0c;直接运行下面命令安装vim sudo apt-get install vim...

Vue3自定义简单的Swiper滑动组件-触控板滑动鼠标滑动左右箭头滑动-demo

代码实现了一个基本的滑动功能&#xff0c;通过鼠标按下、鼠标松开和鼠标移动事件来监听滑动操作。 具体实现逻辑如下&#xff1a; 在 onMounted 钩子函数中&#xff0c;我们为滚动容器添加了三个事件监听器&#xff1a;mousedown 事件&#xff1a;当鼠标按下时&#xff0c;设置…...

三个主流数据库(Oracle、MySQL和SQL Server)的“单表造数

oracle 1.创建表 CREATE TABLE "YZH2_ORACLE" ("VARCHAR2_COLUMN" VARCHAR2(20) NOT NULL ENABLE,"NUMBER_COLUMN" NUMBER,"DATE_COLUMN" DATE,"CLOB_COLUMN" CLOB,"BLOB_COLUMN" BLOB,"BINARY_DOUBLE_COLU…...

TypeScript 中【class类】与 【 接口 Interfaces】的联合搭配使用解读

导读&#xff1a; 前面章节&#xff0c;我们讲到过 接口&#xff08;Interface&#xff09;可以用于对「对象的形状&#xff08;Shape&#xff09;」进行描述。 本章节主要介绍接口的另一个用途&#xff0c;对类的一部分行为进行抽象。 类配合实现接口 实现&#xff08;impleme…...

JavaWeb 手写Tomcat底层机制

目录 一、Tomcat底层整体架构 1.简介 : 2.分析图 : 3.基于Socket开发服务端的流程 : 4.打通服务器端和客户端的数据通道 : 二、多线程模型的实现 1.思路分析 : 2.处理HTTP请求 : 3.自定义Tomcat : 三、自定义Servlet规范 1. HTTP请求和响应 : 1 CyanServletRequest …...

Gof23设计模式之组合模式

1.定义 ​组合模式又名部分整体模式&#xff0c;是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象&#xff0c;用来表示部分以及整体层次。这种类型的设计模式属于结构型模式&#xff0c;它创建了对象组的树形结构。 2.结构 组合模式主要包含三种…...

龙芯积极研发二进制翻译,提升软硬件兼容性,提高LoongArch架构

根据8月8日Phoronix报道&#xff0c;龙芯正在积极研发龙芯二进制翻译功能&#xff08;Loongson Binary Translationm&#xff0c;LBT&#xff09;以提高LoongArch架构与其他处理器&#xff08;如MIPS/x86/Arm&#xff09;的二进制翻译能力&#xff0c;这重要举措将显著提升龙芯…...

3天爆肝整理,自动化测试-YAML文件读写实战(超细总结)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 YAML 简介 YAML&…...

算法通关村——透彻理解二分查找

1. 循环法 public static int binarySearch(int[] arr, int low, int high, int target) {while (low < high) {// 这样写主要是避免溢出的情况&#xff0c;以及>>优先级小于&#xff0c;避免出现死循环int mid low ((high - low) >> 1);if (arr[mid] target…...

PAT(Advanced Level)刷题指南 —— 第六弹(⭐有点难度⭐)

一、1010 Radix 1. 问题重述 2. Sample Input1 6 110 1 103. Sample Output1 24. Sample Input 2 1 ab 1 25. Sample Output 2...

个人对智能家居平台选择的思考

本人之前开发过不少MicroPython程序&#xff0c;其中涉及到自动化以及局域网控制思路&#xff0c;也可以作为智能家居的实现方式。而NodeMCUESPHome的方案具有方便添加硬件、容易更新程序和容量占用小的优势&#xff0c;本人也查看过相关教程后感觉部署ESPHome和编译固件的步骤…...

无涯教程-Lua - while语句函数

只要给定条件为真&#xff0c;Lua编程语言中的 while 循环语句就会重复执行目标语句。 while loop - 语法 Lua编程语言中 while 循环的语法如下- while(condition) dostatement(s) end while loop - 流程图 在这里&#xff0c;需要注意的关键是 while 循环可能根本不执行。…...

MySql学习3:常用函数

常用字符串函数 CHAR_LENGTH(s)&#xff1a;返回字符串的长度 select *, char_length(name) as nameLength from emp;CONCAT(s1,s2…sn)&#xff1a;字符串拼接 select name,concat(name,入职时间&#xff1a;,entrydata) as 入职时间 from emp;CONCAT_WS(x, s1,s2…sn)&a…...

24届近5年江南大学自动化考研院校分析

今天给大家带来的是江南大学控制考研分析 满满干货&#xff5e;还不快快点赞收藏 一、江南大学 学校简介 江南大学&#xff08;Jiangnan University&#xff09;是国家“双一流”建设高校&#xff0c;“211工程”、“985工程优势学科创新平台”重点建设高校&#xff0c;入选…...

C++ 数组

数组是具有一定顺序关系的若干对象的集合体&#xff0c;组成数组的对象称为该数组的元素。 数组元素用数组名与带方括号的下标表示&#xff0c;同一数组的各个元素具有相同的类型。数组可以由除void型以外的任何一种类型构成&#xff0c;构成数组的类型和数组之间的关系&#x…...