电设第一次作业

作业内容

  • 实现LED流水灯
  • 按键实现LED流水灯的开关,加速和监督
  • 实现串口通信,将printf函数重定向到UART

静态变量

1
2
3
int x=0;
int t=0;
int speed=500;

串口通信

原理图:

代码部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include "stm32f10x.h" 
#include <stdio.h>

//我这里使用的是stm32f103c6t6,PA9和PA10为rx和tx
void Serial_Init(){
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO;
GPIO.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO.GPIO_Pin=GPIO_Pin_9;
GPIO.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO);
USART_InitTypeDef USARTInit_Structure;
//设置波特率
USARTInit_Structure.USART_BaudRate=9600;
USARTInit_Structure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
//这个模式下只能写到电脑上
USARTInit_Structure.USART_Mode=USART_Mode_Tx;
//双向通信
//USARTInit_Structure.USART_Mode=USART_Mode_Tx | USART_Mode_Rx;;
//验证位设置
USARTInit_Structure.USART_Parity=USART_Parity_No;
//停止位设置
USARTInit_Structure.USART_StopBits=USART_StopBits_1;
//有效位设置
USARTInit_Structure.USART_WordLength=USART_WordLength_8b;
USART_Init(USART1,&USARTInit_Structure);

USART_Cmd(USART1,ENABLE);

}
//封装一些函数便于之后的使用
void sendbyte(uint8_t t){
USART_SendData(USART1,t);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);


}
void sendarray(uint8_t *Array,uint16_t Length){

uint16_t i;
for(i=0;i<Length;i++){
sendbyte(Array[i]);
}
}
void sendstring(char *string){
uint8_t i;
for(i=0;string[i]!='\0';i++){

sendbyte(string[i]);
}
}
uint32_t Pow(uint32_t x,uint32_t y){
uint32_t result=1;
while(y--){
result*=x;
}
return result;

}
void sendnumber(uint32_t number,uint8_t length){
uint8_t i;
for(i=0;i<length;i++){
sendbyte(number/Pow(10,length-i-1)%10+0x30);
}

}
//printf函数在内部主要是用fputc()进行打印,对fpuc进行重定向就相当于对printf重定义
int fputc(int ch,FILE *f)
{sendbyte(ch);
return ch;
}

LED流水灯的实现

  • 对GPIO口进行初始化
1
2
3
4
5
6
7
8
void ledInit(){	
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO;
GPIO.GPIO_Mode=0x10;
GPIO.GPIO_Pin=GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 |GPIO_Pin_5 ;
GPIO.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO);
}
  • 流水灯函数实现
1
2
3
4
5
6
7
8
9
10
11
void led_flash(int i,int t){

switch(t){
case 0: GPIO_SetBits(GPIOA,GPIO_Pin_1);Delay_ms(i);GPIO_ResetBits(GPIOA,GPIO_Pin_1);break;
case 1: GPIO_SetBits(GPIOA,GPIO_Pin_2);Delay_ms(i);GPIO_ResetBits(GPIOA,GPIO_Pin_2);break;
case 2: GPIO_SetBits(GPIOA,GPIO_Pin_3);Delay_ms(i);GPIO_ResetBits(GPIOA,GPIO_Pin_3);break;
case 3: GPIO_SetBits(GPIOA,GPIO_Pin_4);Delay_ms(i);GPIO_ResetBits(GPIOA,GPIO_Pin_4);break;
case 4: GPIO_SetBits(GPIOA,GPIO_Pin_5);Delay_ms(i);GPIO_ResetBits(GPIOA,GPIO_Pin_5);break;

}
}
  • 按键设置

这里我采用外部中断的方式(在主循环一直扫描GPIO口,会导致cpu性能浪费甚至有可能会导致按键失灵

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
void Exit_init(){
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
GPIO_InitTypeDef GPIOb1;
GPIOb1.GPIO_Mode=GPIO_Mode_IPU;
GPIOb1.GPIO_Pin=GPIO_Pin_11;
GPIOb1.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIOb1);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource11);
EXTI_InitTypeDef EXTI_Init_Structure;
EXTI_Init_Structure.EXTI_Line=EXTI_Line11;
EXTI_Init_Structure.EXTI_LineCmd=ENABLE;
EXTI_Init_Structure.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_Init_Structure.EXTI_Trigger=EXTI_Trigger_Falling;
EXTI_Init(&EXTI_Init_Structure);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_Init_Structure;
NVIC_Init_Structure.NVIC_IRQChannel=EXTI15_10_IRQn;
NVIC_Init_Structure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init_Structure.NVIC_IRQChannelPreemptionPriority=0;
NVIC_Init_Structure.NVIC_IRQChannelSubPriority=0;
NVIC_Init(&NVIC_Init_Structure);

}
void speedup_Init(){
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
GPIO_InitTypeDef GPIOb1;
GPIOb1.GPIO_Mode=GPIO_Mode_IPU;
GPIOb1.GPIO_Pin=GPIO_Pin_15;
GPIOb1.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIOb1);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource15);
EXTI_InitTypeDef EXTI_Init_Structure;
EXTI_Init_Structure.EXTI_Line=EXTI_Line15;
EXTI_Init_Structure.EXTI_LineCmd=ENABLE;
EXTI_Init_Structure.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_Init_Structure.EXTI_Trigger=EXTI_Trigger_Falling;
EXTI_Init(&EXTI_Init_Structure);

}
void speeddown_Init(){
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
GPIO_InitTypeDef GPIOb1;
GPIOb1.GPIO_Mode=GPIO_Mode_IPU;
GPIOb1.GPIO_Pin=GPIO_Pin_12;
GPIOb1.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIOb1);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource12);
EXTI_InitTypeDef EXTI_Init_Structure;
EXTI_Init_Structure.EXTI_Line=EXTI_Line12;
EXTI_Init_Structure.EXTI_LineCmd=ENABLE;
EXTI_Init_Structure.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_Init_Structure.EXTI_Trigger=EXTI_Trigger_Falling;
EXTI_Init(&EXTI_Init_Structure);

  • 主函数实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
int main(){
ledInit();
Exit_init();
speedup_Init();
speeddown_Init();
while(1){
while(x){
printf("%d",x);
led_flash(speed,t);
t=(t+1)%5;
}
if(x==0)
t=0;
}

}
void EXTI15_10_IRQHandler(){
if(EXTI_GetITStatus(EXTI_Line11)==SET){
Easy_Delay_ms(15);
while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_11)==0);
Easy_Delay_ms(15);
x=(x+1)%2;
EXTI_ClearITPendingBit(EXTI_Line11);
}else if(EXTI_GetITStatus(EXTI_Line15)==SET){
Easy_Delay_ms(15);
while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_15)==0);
Easy_Delay_ms(15);
if(speed>100)
speed-=100;
EXTI_ClearITPendingBit(EXTI_Line15);
}else if(EXTI_GetITStatus(EXTI_Line12)==SET){
Easy_Delay_ms(15);
while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_12)==0);
Easy_Delay_ms(15);
if (speed<1000)
speed+=100;
EXTI_ClearITPendingBit(EXTI_Line12);
}
}