准备物件
- STM32F103C8T6核心板
- ST-LINK V2
- DHT11
- 杜邦线若干
连接线
STM32F103C8T6芯片管脚图
管脚说明
连接仿真器
STM32 | ST-LINKV2 |
---|---|
VCC | VCC |
GND | GND |
SWCLK | SWCLK |
SWDIO | SWDIO |
创建工程
参考STM32F103X 开发环境搭建
可将其模板复制一份
添加延时功能
在DRIVER/inc
中添加timer.h
#ifndef __TIMER_H__ #define __TIMER_H__ #include "stm32f10x.h" void systick_init(void); void timing_delay_decrement(void); void delay_us(__IO uint32_t n); #endif
对应的在DRIVER/src
中添加timer.c
#include "timer.h" __IO uint32_t gTimingDelay; /* SystemCoreClock / 1000 --> 1ms */ /* SystemCoreClock / 10000 --> 100us */ /* SystemCoreClock / 100000 --> 10us */ /* SystemCoreClock / 1000000 --> 1us */ void systick_init(void) { while (SysTick_Config(SystemCoreClock / 1000000) == 1); } void timing_delay_decrement(void) { if (gTimingDelay != 0x0) { gTimingDelay--; } } void SysTick_Handler(void) { timing_delay_decrement(); } void delay_us(__IO uint32_t n) { gTimingDelay = n; while(gTimingDelay != 0); }
点亮LED
可以看到核心板上有两个LED灯,PWR(电源)和PC13
修改USER/main.c
#include "stm32f10x.h" #include "timer.h" #define Led_On GPIO_SetBits(GPIOC, GPIO_Pin_13) #define Led_Off GPIO_ResetBits(GPIOC, GPIO_Pin_13) void LED_Init() { GPIO_InitTypeDef s; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); s.GPIO_Pin = GPIO_Pin_13; s.GPIO_Mode = GPIO_Mode_Out_PP; s.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &s); } int main() { SystemInit(); systick_init(); LED_Init(); while (1) { Led_On; delay_us(500000); Led_Off; delay_us(500000); } }
<1> 由于timer.c已经实现SysTick_handler
中断实现,需要编辑USER/stm32f10x_it.c
,将SysTick_handler
函数注释
<2> 右击工程名 -> Options -> C/C++ Compiler -> Preprocessor
在"Additional include directories:"中添加$PROJ_DIR$\USER\inc\
<3> 右击工程名 -> Options -> Debugger -> Setup
在Driver中选择ST-LINK
<4> 右击工程名 -> Options -> ST-LINK -> Setup
在Reset选择Connect during reset
在Interface中选择SWD
<5> 点击编译,然后Download and Debug
-> Go
便可以看到PC13 LED灯均匀的闪烁。
串口发送数据
用于显示DHT11读取的数据
连线方式
USB-TTL | STM32 |
---|---|
VCC | VCC |
GND | GND |
RXD | PA9(TXD) |
TXD | PA10(RXD) |
如果是树莓派,可以查看GPIO管脚说明,按照上述连接即可。
添加DRIVER/inc/usart.h
#ifndef __USART_H_ #define __USART_H_ #include "stm32f10x.h" #include "stm32f10x_rcc.h" #include "stm32f10x_usart.h" #include <stdarg.h> #define WAIT_TC while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) void usart_config(void); void usart_gpio_init(void); void usart_param_config(void); void usart_send_string(char *data); void usart_printf(const char *fmt, ...); #endif
添加DRIVER/src/usart.c
#include "usart.h" void usart_config(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); usart_gpio_init(); usart_param_config(); } void usart_gpio_init(void) { GPIO_InitTypeDef g; g.GPIO_Speed = GPIO_Speed_50MHz; g.GPIO_Pin = GPIO_Pin_9; g.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(GPIOA, &g); g.GPIO_Pin = GPIO_Pin_10; g.GPIO_Mode = GPIO_Mode_IN_FLOATING; //开漏输入 GPIO_Init(GPIOA, &g); } void usart_param_config(void) { USART_InitTypeDef u; u.USART_BaudRate = 9600; u.USART_WordLength = USART_WordLength_8b; //数据位8位 u.USART_StopBits = USART_StopBits_1; //停止位1位 u.USART_Parity = USART_Parity_No; //无校验位 u.USART_HardwareFlowControl = USART_HardwareFlowControl_None; u.USART_Mode = USART_Mode_Tx; USART_Init(USART1, &u); USART_Cmd(USART1, ENABLE); } void usart_send_string(char *data) { char *p = data; while (p < data + strlen(data)) { WAIT_TC; USART_SendData(USART1, *p++); } } void usart_printf(const char *fmt, ...) { va_list ap; char string[64]; va_start(ap, fmt); vsprintf(string, fmt, ap); va_end(ap); usart_send_string(string); }
main.c
添加如下细节
#include "usart.h" int main() { SystemInit(); systick_init(); usart_config(); LED_Init(); while (1) { Led_On; usart_printf("test usart\n"); delay_us(2000000); Led_Off; delay_us(2000000); } }
打开串口工具,linux下是minicom
minicom -b 9600 -D /dev/ttyUSB0
可以看到test usart
字符,说明串口通信正常。
驱动DHT11
连线方式
DHT11 | STM32 |
---|---|
VCC | VCC |
GND | GND |
DATA | PB11 |
添加DRIVER/inc/dht11.h
#ifndef __DHT11_H__ #define __DHT11_H__ #include "timer.h" #include "stm32f10x_gpio.h" #define DHT11_GPIO_TYPE GPIOB #define DHT11_GPIO_PIN GPIO_Pin_11 #define DHT11_RCC RCC_APB2Periph_GPIOB #define DHT11_OUT_H GPIO_SetBits(DHT11_GPIO_TYPE, DHT11_GPIO_PIN) #define DHT11_OUT_L GPIO_ResetBits(DHT11_GPIO_TYPE, DHT11_GPIO_PIN) #define DHT11_IN GPIO_ReadInputDataBit(DHT11_GPIO_TYPE, DHT11_GPIO_PIN) void dht11_gpio_input(void); void dht11_gpio_output(void); u16 dht11_scan(void); u16 dht11_read_bit(void); u16 dht11_read_byte(void); u16 dht11_read_data(u8 buffer[4]); #endif
添加DRIVER/src/dht11.c
#include "dht11.h" void dht11_gpio_input(void) { GPIO_InitTypeDef g; RCC_APB2PeriphClockCmd(DHT11_RCC, ENABLE); g.GPIO_Pin = DHT11_GPIO_PIN; g.GPIO_Speed = GPIO_Speed_50MHz; g.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入 GPIO_Init(DHT11_GPIO_TYPE, &g); } void dht11_gpio_output(void) { GPIO_InitTypeDef g; RCC_APB2PeriphClockCmd(DHT11_RCC, ENABLE); g.GPIO_Pin = DHT11_GPIO_PIN; g.GPIO_Speed = GPIO_Speed_50MHz; g.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_Init(DHT11_GPIO_TYPE, &g); } void dht11_reset(void) { // 按照DHT11手册步骤 dht11_gpio_output(); DHT11_OUT_L; delay_us(19000); DHT11_OUT_H; delay_us(30); dht11_gpio_input(); } u16 dht11_scan(void) { return DHT11_IN; } u16 dht11_read_bit(void) { while (DHT11_IN == RESET); delay_us(40); if (DHT11_IN == SET) { while (DHT11_IN == SET); return 1; } else { return 0; } } u16 dht11_read_byte(void) { u16 i; u16 data = 0; for (i = 0; i < 8; i++) { data <<= 1; data |= dht11_read_bit(); } return data; } u16 dht11_read_data(u8 buffer[5]) { u16 i = 0; dht11_reset(); if (dht11_scan() == RESET) { //检测到DHT11响应 while (dht11_scan() == RESET); while (dht11_scan() == SET); for (i = 0; i < 5; i++) { buffer[i] = dht11_read_byte(); } while (dht11_scan() == RESET); dht11_gpio_output(); DHT11_OUT_H; u8 checksum = buffer[0] + buffer[1] + buffer[2] + buffer[3]; if (checksum != buffer[4]) { // checksum error return 1; } } return 0; }
修改USER/main.c
#include "dht11.h" int main() { SystemInit(); systick_init(); usart_config(); LED_Init(); while (1) { Led_On; u8 buffer[5]; double hum; double temp; if (dht11_read_data(buffer) == 0) { hum = buffer[0] + buffer[1] / 10.0; temp = buffer[2] + buffer[3] / 10.0; } usart_printf("___{\"temperature\": %.2f, \"humidness\": %.2f}___\n", temp, hum); delay_us(2000000); Led_Off; delay_us(2000000); } }
编译、运行,发现串口可以收到温度信息。
minicom -b 9600 -D /dev/ttyUSB0
来源:https://www.cnblogs.com/rainmote/p/7591256.html