嵌入式入门工程-简单电子温度计(一)

发布于:2024-12-18 ⋅ 阅读:(44) ⋅ 点赞:(0)
  • 先大致确定硬件
    一个stm32f103C8最小系统作控制,DS8B20温度检测模块,8个LED数码管,74HC138D作3位到8位的扩展来作位选择,74HC245作信号放大来驱动数码管显示。

  • 建立工程文件夹SimpleElectronicThermometer,开发keil5,project -> new uvision project,建立一个工程。

  • Select Device for Target 界面选择STMicroelectronics->STM32F1 Series->STM32F103->STM32F103C8

  • 在Target下面Add Group

    1. CMSIS: Cortex Microcontroller Software Interface Standard,微控制器软件接口标准, 来存放CMSIS Cortex-M3 Core Peripheral Access Layer System库 与 CMSIS Cortex-M3 Device Peripheral Access Layer System库。
    2. User: 存放main与自定义中断程序
    3. App:存放项目自定义的库
    4. StdPeriph_Driver: 存放标准外设驱动库
  • 设置好工程的头文件引用目录

  • 写一段GPIO输出来测试工程是否正常

#include "stm32f10x.h"

int main(void) {
	GPIO_InitTypeDef gpioInitVar;
	
	/*启用时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	/* 初始化 PA0 引脚 */
	GPIO_StructInit(&gpioInitVar);
	gpioInitVar.GPIO_Mode = GPIO_Mode_Out_PP;
	gpioInitVar.GPIO_Pin = GPIO_Pin_0;
	gpioInitVar.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&gpioInitVar);
	
	/* PA0引脚置0 */
	GPIO_ResetBits(GPIOA,GPIO_Pin_0);

	while(1);
}

简单说明GPIO的Mode
Stm32的GPIO有8种工作模式

  1. GPIO_Mode_AIN 模拟输入,GPIO会失效,引脚直接接入内部ADC。
  2. GPIO_Mode_IN_FLOATING 浮空输入,如果在该引脚悬空(无信号输入)的情况下,读取该端口的电平是不确定的。
  3. GPIO_Mode_IPD 下拉输入 ,悬空时默认为低电平。
  4. GPIO_Mode_IPU 上拉输入 ,悬空时默认为高电平。
  5. GPIO_Mode_Out_OD 开漏输出,当CPU输出逻辑0时,I/O端口输出低电平;而当CPU输出逻辑1时,该引脚处于开漏,也就是浮空状态(高阻态)。
  6. GPIO_Mode_Out_PP 推挽输出,当CPU输出逻辑0时,I/O端口输出低电平,而当CPU输出逻辑1时,I/O端口输出高电平。
  7. GPIO_Mode_AF_OD 复用开漏输出。
  8. GPIO_Mode_AF_PP 复用推挽输出。
  • 接着来测试下usart 串口输出是否正常,工程中使用串口输出日志到电脑来调试程序。
    先像使用GPIO一样使用USART
#include "stm32f10x.h"

#define DefaultDelayDuration (0xfff)

void delay(u16 duration){ u16 i=110; while(duration--) while(i--); }
const char str[] = "hello world\r\n";

int main(void)
{
	u16 i=0,sz=sizeof(str);
	USART_InitTypeDef usart1InitVar;
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//TX			   //´®¿ÚÊä³öPA9
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;	    //¸´ÓÃÍÆÍìÊä³ö
	GPIO_Init(GPIOA,&GPIO_InitStructure);  /* ³õʼ»¯´®¿ÚÊäÈëIO */
	
	
	usart1InitVar.USART_BaudRate = 9600;
	usart1InitVar.USART_StopBits = USART_StopBits_1;
	usart1InitVar.USART_WordLength = USART_WordLength_8b;
	usart1InitVar.USART_Parity = USART_Parity_No;
	usart1InitVar.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	usart1InitVar.USART_Mode = USART_Mode_Tx;
	USART_Init(USART1,&usart1InitVar);
	USART_Cmd(USART1, ENABLE);  //ʹÄÜ´®¿Ú1 
	USART_ClearFlag(USART1, USART_FLAG_TC);
	
	while(1)
	{
			for (i=0;i<sz;++i) {
				USART_SendData(USART1,str[i]);
				while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
			}
			// delay(100);
	}
}

烧录测试后,无法在电脑端查看到输出。
查看芯片的引脚定义。
在这里插入图片描述
USART1的写端口USART1_TX与PA9是复用的。
所以要启用PA9引脚

#include "stm32f10x.h"

const char str[] = "hello world\r\n";

int main(void)
{
	u16 i=0,sz=sizeof(str);
	USART_InitTypeDef usart1InitVar;
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;// PA9 与 USART1_TX 复用
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;	    // 复用推挽输出
	GPIO_Init(GPIOA,&GPIO_InitStructure);  
	
	usart1InitVar.USART_BaudRate = 9600;
	usart1InitVar.USART_StopBits = USART_StopBits_1;
	usart1InitVar.USART_WordLength = USART_WordLength_8b;
	usart1InitVar.USART_Parity = USART_Parity_No;
	usart1InitVar.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	usart1InitVar.USART_Mode = USART_Mode_Tx;
	USART_Init(USART1,&usart1InitVar);
	USART_Cmd(USART1, ENABLE);  // 使能 USART1
	USART_ClearFlag(USART1, USART_FLAG_TC); 
	
	while(1)
	{
			for (i=0;i<sz;++i) {
				USART_SendData(USART1,str[i]);
			}
	}
}

烧录测试时发现,串口调试工具上是显示有接收数据的,但接受区没看到字符串,可能是太快了,加个延时试试。

#include "stm32f10x.h"

#define DefaultDelayDuration (0xfff)
void delay(u16 duration) {u16 i = 120; while(i--) while(duration--) ; }
const char str[] = "hello world\r\n";

int main(void)
{
	u16 i=0,sz=sizeof(str);
	USART_InitTypeDef usart1InitVar;
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;// PA9 与 USART1_TX 复用
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;	    // 复用推挽输出
	GPIO_Init(GPIOA,&GPIO_InitStructure);  
	
	usart1InitVar.USART_BaudRate = 9600;
	usart1InitVar.USART_StopBits = USART_StopBits_1;
	usart1InitVar.USART_WordLength = USART_WordLength_8b;
	usart1InitVar.USART_Parity = USART_Parity_No;
	usart1InitVar.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	usart1InitVar.USART_Mode = USART_Mode_Tx;
	USART_Init(USART1,&usart1InitVar);
	USART_Cmd(USART1, ENABLE);  // 使能 USART1
	USART_ClearFlag(USART1, USART_FLAG_TC); 
	
	while(1)
	{
			for (i=0;i<sz;++i) {
				USART_SendData(USART1,str[i]);
				delay(DefaultDelayDuration);
			}
	}
}

烧录测试可以看到串口调试工具上缓慢的一行行输出hello world
其实正确的作法是等待上一个数据传输完成后,再传输下一个数据,把延时改成 while(USART_GetFlagStatus(USART1,USART_FLAG_TC) != SET);
现在重定向一下printf 函数,只要重写 fputc 函数就好了,然后包装一个日志打印,在DEBUG模式下输出日志。

#include "stm32f10x.h"
#include <stdio.h>

int fputc(int ch,FILE *p)  
{
	USART_SendData(USART1,(u8)ch);	
	while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
	return ch;
}

#define _DEBUG_

#ifdef _DEBUG_
#define debug_log(args,...) printf(args,##__VA_ARGS__)
#else
#define debug_log(args,...) ((void)0)
#endif

int main(void)
{
	USART_InitTypeDef usart1InitVar;
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;	    
	GPIO_Init(GPIOA,&GPIO_InitStructure);  
	
	usart1InitVar.USART_BaudRate = 9600;
	usart1InitVar.USART_StopBits = USART_StopBits_1;
	usart1InitVar.USART_WordLength = USART_WordLength_8b;
	usart1InitVar.USART_Parity = USART_Parity_No;
	usart1InitVar.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	usart1InitVar.USART_Mode = USART_Mode_Tx;
	USART_Init(USART1,&usart1InitVar);
	USART_Cmd(USART1, ENABLE);  
	USART_ClearFlag(USART1, USART_FLAG_TC); 
	
	while(1)
	{
		debug_log("hello world\r\n");
	}
}

这里用到一个宏函数技巧#define debug_log(args,...) printf(args,##__VA_ARGS__)

下篇继续


网站公告

今日签到

点亮在社区的每一天
去签到