上一篇:[嵌入式软件][启蒙篇][仿真平台] STM32F103实现LED、按键
文章目录
- 一、串口输出
- (1) 简介
- (2) 示例代码
- (3) 仿真效果
- 二、串口输入
- (1) 简介
- (2) 示例代码
- (3) 仿真效果
- 三、ADC采集
- (1) 简介
- (2) 采集电压
- (3) 示例代码(电压)
- (4) 仿真效果 (电压)
- (5) 采集光敏
- (6) 示例代码(光敏)
- (6) 仿真效果 (光敏)
- (7) 内部温度
- (8) 示例代码(内部温度)
- (9) 仿真效果 (内部温度)
一、串口输出
(1) 简介
- 学C语言时,使用的printf()函数,就是通过串口打印出来的。
- 跟外部器件通信,比如GPS模块、蓝牙模块、wifi模块;
- 两个开发板之间通信,制定私有协议。
- PC电脑通信,使用上位机显示数据或控制下位机。
(2) 示例代码
#include <stdint.h>
#include <stdio.h>
#include "sys.h"
#include "stm32f10x_conf.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "usart.h"
int main() {
// LED初始化
LED_Init();
// 按键初始化
KEY_Init();
//串口初始化
uart_init(115200);
// 由于LED接了VCC, 引脚高电平,无法导通电路,所以低电平点亮,即VCC(火线)-->GND(地线/零线)
while(1) {
if (Key_Scan(GPIOA, GPIO_Pin_1)) { // 检测按键整个过程。按下->松开
LED = !LED; // 每次按下,切换开关。低电平点亮 高电平熄灭
printf("key pressed. led state:%u\n", LED);
}
}
}
(3) 仿真效果
- 操作:打开串口–按下按键
二、串口输入
(1) 简介
- 跟外部器件通信,比如GPS模块、蓝牙模块、wifi模块;
- 两个开发板之间通信,制定私有协议。
- PC电脑通信,使用上位机输入参数或控制下位机。
(2) 示例代码
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "sys.h"
#include "stm32f10x_conf.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "usart.h"
int main() {
// LED初始化
LED_Init();
// 按键初始化
KEY_Init();
//串口初始化
uart_init(115200);
// 由于LED接了VCC, 引脚高电平,无法导通电路,所以低电平点亮,即VCC(火线)-->GND(地线/零线)
while(1) {
if (Key_Scan(GPIOA, GPIO_Pin_1)) { // 检测按键整个过程。按下->松开
LED = !LED; // 每次按下,切换开关。低电平点亮 高电平熄灭
printf("key pressed. led state:%u\n", LED);
}
if ((USART_RX_STA & 0x8000) == 0x8000) { // 接收完成
printf("rx:%s\r\n", USART_RX_BUF); // 打印刚刚接收的数据
USART_RX_STA = 0; // 继续接收数据
memset(USART_RX_BUF, 0, USART_REC_LEN); // 将刚刚接收到的数据清空
}
}
}
重点:还有一个地方需要小修改(平台没有实现,我们这里替换下就行),有兴趣可以研究下功能的实现
void USART1_IRQHandler(void) { //串口1中断服务程序
uint16_t Res;
// 接收中断(接收到的数据必须是0x0d 0x0a结尾, 就是换行符\r\n)
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
Res = USART_ReceiveData(USART1); //读取接收到的数据
if ((USART_RX_STA & 0x8000) == 0) { //接收未完成
if (USART_RX_STA & 0x4000) { //接收到了0x0d
if (Res != 0x0a)
USART_RX_STA = 0; //接收错误,重新开始
else
USART_RX_STA |= 0x8000; //接收完成了
} else { //还没收到0X0D
if (Res == 0x0d)
USART_RX_STA |= 0x4000;
else {
USART_RX_BUF[USART_RX_STA & 0X3FFF] = Res;
USART_RX_STA++;
if (USART_RX_STA > (USART_REC_LEN - 1))
USART_RX_STA = 0; //接收数据错误,重新开始接收
}
}
}
}
}
(3) 仿真效果
- 操作:打开串口–发送消息:123456\r\n
三、ADC采集
这个实验需要添加电路,如下图:
- 将按钮移除
- 添加电压调节器
(1) 简介
- ADC是一个专门采集模拟量转为为数字信号的外设。
- ADC一般采集电压、电流、光敏(光亮度)、温度、湿度、压力、声音等等。
(2) 采集电压
本实验使用STM32采样ADC模拟输入器的数据,开启仿真后,串口助手将ADC数值与转换出的电压值一并打印。
(3) 示例代码(电压)
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "sys.h"
#include "stm32f10x_conf.h"
#include "delay.h"
#include "led.h"
#include "adc.h"
#include "usart.h"
uint32_t adc_value = 0;
float voltage_value = 0; //用于保存转换计算后的电压值
int main() {
// LED初始化
LED_Init();
// ADC1通道1初始化
Adc_Init();
//串口初始化
uart_init(115200);
while(1) {
// 通过ADC_GetConversionValue函数查询ADC的DR寄存器获取ADC转换结果值
adc_value = Get_Adc(1);
// 计算出模拟输入的电压值
voltage_value=(float)adc_value*(3.3/4095);
// 打印ADC转换结果值
printf("AD value is %d\n", adc_value);
//打印计算出的电压值
printf("voltage value is %f V\n", voltage_value);
LED = !LED;
delay_ms(50);
}
}
(4) 仿真效果 (电压)
- 操作: 打开串口–调整电压
(5) 采集光敏
- 光敏电阻的特性:光线越亮,阻值越小。
- 一般用于走廊,白天不亮,晚上亮,做到省电的效果。
- 按下图搭建电路
(6) 示例代码(光敏)
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "sys.h"
#include "stm32f10x_conf.h"
#include "delay.h"
#include "led.h"
#include "adc.h"
#include "usart.h"
//设定基于ADC信号的模拟光强阈值
#define lux 2200
uint32_t adc_value = 0;
int main() {
// LED初始化
LED_Init();
// ADC1通道1初始化
Adc_Init();
//串口初始化
uart_init(115200);
while(1) {
// 通过ADC_GetConversionValue函数查询ADC的DR寄存器获取ADC转换结果值
adc_value = Get_Adc(1);
// 打印ADC转换结果值
printf("AD value is %d\n", adc_value);
if (adc_value > lux) {
LED = 0; // 点亮
} else {
LED = 1; // 熄灭
}
delay_ms(50);
}
}
(6) 仿真效果 (光敏)
- 操作:打开串口–调节光敏电阻–从0-100%调整–当阻值>2000,点亮;阻值<2000,熄灭。
(7) 内部温度
- 芯片内部温度,目的:让电阻计算更佳准确,因为温度会影响阻值。 (一般用不上,不精确)
- 测量CPU以及周围的温度,测量范围为-40~125度,误差为±1.5度
- 内部温度传感器更适合于检测温度的变化,需要测量精确温度的情况下,应使用外置传感器。
- 温度传感器模拟输入推荐采样时间是 17.1us。
- 温度的计算公式如下:
T(℃)= {( V25-Vsense)/ Avg_Slope} + 25
上式中:V25=Vsense 在 25 度时的数值(典型值为: 1.43)。
Avg_Slope=温度与 Vsense 曲线的平均斜率(单位: mv/℃或 uv/℃)(典型值: 4.3mv/℃)。
(8) 示例代码(内部温度)
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "sys.h"
#include "stm32f10x_conf.h"
#include "delay.h"
#include "led.h"
#include "adc.h"
#include "usart.h"
float temperate = 0; //用于保存转换计算后的温度值
uint32_t adc_value = 0;
int main() {
// LED初始化
LED_Init();
// ADC1通道1初始化
Adc_Init();
//串口初始化
uart_init(115200);
while(1) {
// 通过ADC_GetConversionValue函数查询ADC的DR寄存器获取ADC转换结果值
adc_value = Get_Adc(1);
// 打印ADC转换结果值
printf("AD value is %d\n", adc_value);
temperate = (float)adc_value * (3.3 / 4095); // 先转成电压值
temperate = (1.43 - temperate) / 0.0043 + 25; // 再转换为温度值
//打印计算出的温度值
printf("MCU temperature is %f C \n", temperate);
LED = !LED;
delay_ms(50);
}
}
(9) 仿真效果 (内部温度)
下一篇:[嵌入式软件][启蒙篇][仿真平台]STM32F103实现定时器