嵌入式实训——day3

咪乐|直播|官方下载地址 莫要以为网络是法制的漏网之鱼,其实互联网最大也大不过法网。

资料大小: 1.82MB

所需积分: 0

下载次数:

用户评论: 0条评论,查看

上传日期: 2021-12-01

上 传 者: 发烧友他上传的所有资料

资料介绍

标签:89C52型单片机(8)STM32(5786)

在为期两天的C语言知识回顾之后,我们开始做stm32的基础实验

今天的基础实验内容有:1、点亮一个led灯(呼吸灯的实现)2、定时器的使用 3、串口通信实验

在实验之前呢,需要安装一些软件

链接:http://pan.b.cristian-ronaldo.comaidu.com/s/1A8gFiggPVYl8rzdk-Ym99Q?
提取码:uy2c?
(里面有软件及安装说明,个人建议安装软件时 以管理员的身份打开)

在一切做好之后呢,我们开始做实验

一、呼吸灯实验

? ? 实验环境:FS-STM32F103开发平台、STM32CubeMX图形开发软件、Keil软件

?原理其实就是三个不同颜色的led灯,通过颜色强弱组合可以变成不同的颜色。

具体步骤:

? 1、打开STM32CubeMX—>点击new project

? 2、选择MCU,本次用的芯片为STM32F103

3、配置引脚或选择外设(PB8/PB7/PB6设置为GOPIO_Output)

4、配置时钟(默认时钟8MHZ)

5、创建工程:点击上方project—>SetTIngs

注:工程名和路径必须为英文,如果有中文会出现生成代码不成功的现象,编译器型号选择MDK-ARM V5

6、在code generator里面勾选Generate files的第一个,选择模块化生成代码

?7、打开工程,编写程序

?8、往开发板下载程序

9、查看实验结果

10、代码部分

相应的地方添加如下代码(必须在正确位置添加,不然下次重新生成工程时会被覆盖)

延时函数声明:

1
2
3
4

?

/*?USER?CODE?BEGIN?PFP?*/
/*?Private?funcTIon?prototypes?-----------------------------------------------*/

void?delay_nus(uint16_t?TIme);
/*?USER?CODE?END?PFP?*/

?

led灯代码?

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

?

?

??/*?USER?CODE?BEGIN?3?*/
????/****************以下是呼吸灯程序**************/
????????for(i=0;?i<500;?i++)
????{?
/*GPIOB表示PB类端口,GPIO_PIN_8表示PB8端口,?GPIO_PIN_SET设置为1高电平*/????
????????HAL_GPIO_WritePin(GPIOB,?GPIO_PIN_8,?GPIO_PIN_SET);
????????delay_nus(i);
/*递增延时*/

??????? /*GPIO_PIN_SET设置为0低电平*/?
????????HAL_GPIO_WritePin(GPIOB,?GPIO_PIN_8,?GPIO_PIN_RESET);
????????delay_nus(500-i);
/*递减延时*/
????}
????????
for(i=0;?i<500;?i++)
????{???????
????????HAL_GPIO_WritePin(GPIOB,?GPIO_PIN_8,?GPIO_PIN_RESET);
????????delay_nus(i);
????????HAL_GPIO_WritePin(GPIOB,?GPIO_PIN_8,?GPIO_PIN_SET);
????????delay_nus(500-i);
????}
????????
/*************以下是三色小灯轮流闪烁*************/
//??????HAL_GPIO_WritePin(GPIOB,?GPIO_PIN_8,?GPIO_PIN_RESET);
//??????HAL_Delay(1000);
//??????HAL_GPIO_WritePin(GPIOB,?GPIO_PIN_8,?GPIO_PIN_SET);
//??????HAL_Delay(1000);
//??????HAL_GPIO_WritePin(GPIOB,?GPIO_PIN_7,?GPIO_PIN_RESET);
//??????HAL_Delay(1000);
//??????HAL_GPIO_WritePin(GPIOB,?GPIO_PIN_7,?GPIO_PIN_SET);
//??????HAL_Delay(1000);
//??????HAL_GPIO_WritePin(GPIOB,?GPIO_PIN_6,?GPIO_PIN_RESET);
//??????HAL_Delay(1000);
//??????HAL_GPIO_WritePin(GPIOB,?GPIO_PIN_6,?GPIO_PIN_SET);
//??????HAL_Delay(1000);

??}
??
/*?USER?CODE?END?3?*/

?

?

?

?

延时函数定义

1
2
3
4
5
6
7
8
9
10
11

?

/*?USER?CODE?BEGIN?4?*/
void?delay_nus(uint16_t?TIme)
{????
???uint16_t?i=
0;??
???while(time--)
???{
??????i=
10;?
??????while(i--)?;????
???}
}

/*?USER?CODE?END?4?*/

二、定时器实验

? 实验原理:

stm32F103芯片提供了8个定时器,其中两个TIM1和TIM8是高级定时器,其余为通用定时器。

TIM1和TIM8挂在APB2总线上,而TIM2-TIM7则挂在APB1总线上。其中TIM1&TIM8称为高级控制定时器(advanced control timer).他们所在的APB2总线也比APB1总线要好。APB2可以工作在72MHz下,而APB1最大是36MHz。

? 软件配置:

使用内部时钟源

参考代码:

在main.c里添加如下代码

1
2
3
4

?

??/*?USER?CODE?BEGIN?2?*/

?/*设置PB6端口为0*/
????HAL_GPIO_WritePin(GPIOB,?GPIO_PIN_6,?GPIO_PIN_RESET);

/*开启时钟*/
????HAL_TIM_Base_Start_IT(&htim2);
??
/*?USER?CODE?END?2?*/

?

在中断处理函数stm32f1xx_it.c中

我们看到中断处理函数里是调用了另外一个函数,

1
2
3
4
5
6
7
8
9
10
11
12
13

?

/**
*?@brief?This?function?handles?TIM2?global?interrupt.
*/

/*TIME2定时器中断控制*/
void?TIM2_IRQHandler(void)
{
??
/*?USER?CODE?BEGIN?TIM2_IRQn?0?*/

??/*?USER?CODE?END?TIM2_IRQn?0?*/

? /*时钟中断控制调用*/
??HAL_TIM_IRQHandler(&htim2);
??
/*?USER?CODE?BEGIN?TIM2_IRQn?1?*/

??/*?USER?CODE?END?TIM2_IRQn?1?*/
}

追踪一下

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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131

?

/**
??*?@brief??This?function?handles?TIM?interrupts?requests.
??*?@param??htim?:?TIM??handle
??*?@retval?None
??*/

? /*时钟中断处理函数*/
void?HAL_TIM_IRQHandler(TIM_HandleTypeDef?*htim)
{
??
/*?Capture?compare?1?event?*/
??if(__HAL_TIM_GET_FLAG(htim,?TIM_FLAG_CC1)?!=?RESET)
??{
????
if(__HAL_TIM_GET_IT_SOURCE(htim,?TIM_IT_CC1)?!=RESET)
????{
??????{
????????__HAL_TIM_CLEAR_IT(htim,?TIM_IT_CC1);
????????htim->Channel?=?HAL_TIM_ACTIVE_CHANNEL_1;

????????
/*?Input?capture?event?*/
????????if((htim->Instance->CCMR1?&?TIM_CCMR1_CC1S)?!=?0x00)
????????{
??????????HAL_TIM_IC_CaptureCallback(htim);
????????}
????????
/*?Output?compare?event?*/
????????else
????????{
??????????HAL_TIM_OC_DelayElapsedCallback(htim);
??????????HAL_TIM_PWM_PulseFinishedCallback(htim);
????????}
????????htim->Channel?=?HAL_TIM_ACTIVE_CHANNEL_CLEARED;
??????}
????}
??}
??
/*?Capture?compare?2?event?*/
??if(__HAL_TIM_GET_FLAG(htim,?TIM_FLAG_CC2)?!=?RESET)
??{
????
if(__HAL_TIM_GET_IT_SOURCE(htim,?TIM_IT_CC2)?!=RESET)
????{
??????__HAL_TIM_CLEAR_IT(htim,?TIM_IT_CC2);
??????htim->Channel?=?HAL_TIM_ACTIVE_CHANNEL_2;
??????
/*?Input?capture?event?*/
??????if((htim->Instance->CCMR1?&?TIM_CCMR1_CC2S)?!=?0x00)
??????{
????????HAL_TIM_IC_CaptureCallback(htim);
??????}
??????
/*?Output?compare?event?*/
??????else
??????{
????????HAL_TIM_OC_DelayElapsedCallback(htim);
????????HAL_TIM_PWM_PulseFinishedCallback(htim);
??????}
??????htim->Channel?=?HAL_TIM_ACTIVE_CHANNEL_CLEARED;
????}
??}
??
/*?Capture?compare?3?event?*/
??if(__HAL_TIM_GET_FLAG(htim,?TIM_FLAG_CC3)?!=?RESET)
??{
????
if(__HAL_TIM_GET_IT_SOURCE(htim,?TIM_IT_CC3)?!=RESET)
????{
??????__HAL_TIM_CLEAR_IT(htim,?TIM_IT_CC3);
??????htim->Channel?=?HAL_TIM_ACTIVE_CHANNEL_3;
??????
/*?Input?capture?event?*/
??????if((htim->Instance->CCMR2?&?TIM_CCMR2_CC3S)?!=?0x00)
??????{
????????HAL_TIM_IC_CaptureCallback(htim);
??????}
??????
/*?Output?compare?event?*/
??????else
??????{
????????HAL_TIM_OC_DelayElapsedCallback(htim);
????????HAL_TIM_PWM_PulseFinishedCallback(htim);
??????}
??????htim->Channel?=?HAL_TIM_ACTIVE_CHANNEL_CLEARED;
????}
??}
??
/*?Capture?compare?4?event?*/
??if(__HAL_TIM_GET_FLAG(htim,?TIM_FLAG_CC4)?!=?RESET)
??{
????
if(__HAL_TIM_GET_IT_SOURCE(htim,?TIM_IT_CC4)?!=RESET)
????{
??????__HAL_TIM_CLEAR_IT(htim,?TIM_IT_CC4);
??????htim->Channel?=?HAL_TIM_ACTIVE_CHANNEL_4;
??????
/*?Input?capture?event?*/
??????if((htim->Instance->CCMR2?&?TIM_CCMR2_CC4S)?!=?0x00)
??????{
????????HAL_TIM_IC_CaptureCallback(htim);
??????}
??????
/*?Output?compare?event?*/
??????else
??????{
????????HAL_TIM_OC_DelayElapsedCallback(htim);
????????HAL_TIM_PWM_PulseFinishedCallback(htim);
??????}
??????htim->Channel?=?HAL_TIM_ACTIVE_CHANNEL_CLEARED;
????}
??}
?
?/*?TIM?Update?event?*/
??if(__HAL_TIM_GET_FLAG(htim,?TIM_FLAG_UPDATE)?!=?RESET)
??{
????if(__HAL_TIM_GET_IT_SOURCE(htim,?TIM_IT_UPDATE)?!=RESET)
????{
??????__HAL_TIM_CLEAR_IT(htim,?TIM_IT_UPDATE);
??????HAL_TIM_PeriodElapsedCallback(htim);
//回调函数
????}
??}

??/*?TIM?Break?input?event?*/
??if(__HAL_TIM_GET_FLAG(htim,?TIM_FLAG_BREAK)?!=?RESET)
??{
????
if(__HAL_TIM_GET_IT_SOURCE(htim,?TIM_IT_BREAK)?!=RESET)
????{
??????__HAL_TIM_CLEAR_IT(htim,?TIM_IT_BREAK);
??????HAL_TIMEx_BreakCallback(htim);
????}
??}
??
/*?TIM?Trigger?detection?event?*/
??if(__HAL_TIM_GET_FLAG(htim,?TIM_FLAG_TRIGGER)?!=?RESET)
??{
????
if(__HAL_TIM_GET_IT_SOURCE(htim,?TIM_IT_TRIGGER)?!=RESET)
????{
??????__HAL_TIM_CLEAR_IT(htim,?TIM_IT_TRIGGER);
??????HAL_TIM_TriggerCallback(htim);
????}
??}
??
/*?TIM?commutation?event?*/
??if(__HAL_TIM_GET_FLAG(htim,?TIM_FLAG_COM)?!=?RESET)
??{
????
if(__HAL_TIM_GET_IT_SOURCE(htim,?TIM_IT_COM)?!=RESET)
????{
??????__HAL_TIM_CLEAR_IT(htim,?TIM_FLAG_COM);
??????HAL_TIMEx_CommutationCallback(htim);
????}
??}
}

?

红色标记部分即是我们需要实现的函数。这是一个回调函数,就是当发生中断时调用这个函数,我们可在重写此函数

我们可以将其写在main.c的USER CODE 4 部分

1
2
3
4
5
6

?

/*?USER?CODE?BEGIN?4?*/
void?HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef?*htim)
{
????HAL_GPIO_TogglePin(GPIOB,?GPIO_PIN_6);
/*PB6端口配置高电平,即点LED*/
}
/*?USER?CODE?END?4?*/

三、串口通信实验

? 实验原理:

UART和USART的区别:

UART:universal asynchronous receiver and transmitter通用异步收发器USART:universal synchronous asynchronous receiver and transmitter通用同步异步收发器。
从名字上可以看出,USART在UART基础上增加了同步功能,即USART是UART的增强型,事实也确实是这样。但是具体增强到了什么地方呢?
其实当我们使用USART在异步通信的时候,它与UART没有什么区别,但是用在同步通信的时候,区别就很明显了:大家都知道同步通信需要时钟来触发数据传输,也就是说USART相对UART的区别之一就是能提供主动时钟。如stm32的USART可以提供时钟支持ISO7816的智能卡接口
一般而言,单片机中,名称为UART的接口一般只能用于异步串行通讯,而名称为USART的接口既可以用于同步串行通讯,也能用于异步串行通讯。

?

?

参考代码:

在main函数里写一个以中断方式接受的串口函数

定义一个用来接收数据的数组?

1
2
3
4

?

?

*?USER?CODE?BEGIN?PV?*/
/*?Private?variables?---------------------------------------------------------*/

????uint8_t?RxData[6];
/*?USER?CODE?END?PV?*/

?//打开通道1PWM,那么PB6这个灯就会被点亮

1
2
3
4
5
6
7
8
9
10
11
12
13
14

?

?

??/*?USER?CODE?BEGIN?2?*/
????HAL_TIM_PWM_Start(&htim4,?TIM_CHANNEL_1);//打开小灯
??/*?USER?CODE?END?2?*/

??/*?Infinite?loop?*/
??/*?USER?CODE?BEGIN?WHILE?*/
??while?(1)
??{
??
/*?USER?CODE?END?WHILE?*/

??/*?USER?CODE?BEGIN?3?*/
????HAL_UART_Receive_IT(&huart1,RxData,?6);
??}
??
/*?USER?CODE?END?3?*/

?

这里我们在usart.c中去写中断回调函数(也可以在main.c USER CODE BEGIN 4里面写)

回调函数函数里面实现的就是将我们接收到的数据发送到串口助手去显示:

1
2
3
4
5
6

?

/*?USER?CODE?BEGIN?1?*/
void?HAL_UART_RxCpltCallback(UART_HandleTypeDef?*UartHandle)
{
????HAL_UART_Transmit(&huart1,RxData,
6,10);
}

/*?USER?CODE?END?1?*/

?

HAL库提供的接收和发送函数都会指定长度,这里就体现了协议的优势了,如我们这里定义了一个uint8_t RxData[6]的数组,接收和发送都指定长度。

?

?

用户评论

查看全部 条评论

发表评论请先 , 还没有账号?免费注册

发表评论

用户评论
技术交流、我要发言! 发表评论可获取积分! 请遵守相关规定。
上传电子资料
百度