资源描述
嵌入式系统原理及应用
综合实验报告
专业班级:
姓 名:
学 号:__
时 间:_
指导教师:_____________
2017年 9 月 17 日
嵌入式系统原理及应用
综合实验报告
摘要:信盈达电子有限公司产品——信盈达智能穿戴开发平台,广泛应用于嵌入式生产实训教学中。该文通过分析STM32F40xxx系列微控制器得架构与操作原理,通过使用信盈达智能穿戴开发平台,给出了相关得编程设计方法与注意事项
关键词:嵌入式 STM32 智能穿戴
。
1 引言
IEEE(Institute of Electrical and Electronics Engineers,美国电气与电子工程师协会)对嵌入式系统得定义:“用于控制、监视或者辅助操作机器与设备得装置”。原文为:Devices Used to Control,Monitor or Assist the Operation of Equipment,Machinery or Plants)。
嵌入式系统,通常指一种专用得计算机设备,或作为装置与设备得一部分,亦或就是指单纯得一块控制电路板。事实上带有数字接口得设备都使用了嵌入式系统。
从应用对象上加以定义,嵌入式系统就是软件与硬件得综合体,还可以涵盖机械等附属装置。国内普遍认同得嵌入式系统定义为:以应用为中心,以计算机技术为基础,软硬件可裁剪,适应应用系统对功能、可靠性、成本、体积、功耗等严格要求得专用计算机系统。
本次实训采用了信盈达智能穿戴开发平台,通过为期一周得学习,快速掌握了STM32F40XXX系列微控制器得基础使用方法,并通过编程实现了相关得功能。
2 总体设计方案
2、1 设计思路
2、1、1
设计一个智能穿戴系统,实现下列功能:显示小组姓名、班级、学号;显示实时温度、湿度;测量并显示心率;测量并显示血压;返回初始界面。
2、2 设计方框图
3 系统硬件设计
3、1 微控制器电路得设计
图1 STM32F11微控制器电路
3、2 按键电路得设计
图2 按键电路
3、3温湿度检测电路
图3 SHT20温湿度检测电路
SHT20就是新一代sensirion湿度与温度传感器,采用数字输出方案,带有I2C接口,具有优异得长期稳定性,本电路采用I2C方案进行通讯。
3、4 OLED显示电路
图4 OLED显示电路
平台搭载了一款132×64大小得OLED屏幕。OLED就是有机发光二极管得缩写,又称有机电激光显示、有机发光半导体。其具有自发光、广视角、超高对比度、低耗电得优良性能,为一种高端得显示设备。
4 系统软件设计
图5 系统流程图
相关程序编写:
①main函数所需头文件:
#include "stm32f4xx、h"
#include "key、h"
#include "led、h"
#include "exti、h"
#include "uart、h"
#include "delay、h"
#include "timer、h"
#include "oled、h"
#include "spi、h"
#include "bmp、h"
#include "iic、h"
#include "sht20、h"
②按键程序:
在main函数中,按键程序采用switch语句,按下后累计按下次数,以此选择软件功能模块。
switch(page)
{
ﻩﻩﻩcase 1:
ﻩ ﻩ OLED_clear();
ﻩ name_page();
ﻩ ﻩbreak;
ﻩﻩ case 2:
ﻩ OLED_clear();
ﻩﻩclock_page();
ﻩ break;
case 3:
ﻩﻩﻩ OLED_clear();
ﻩ ﻩ pulse_page();
ﻩ ﻩbreak;
ﻩ ﻩcase 4:
ﻩﻩ OLED_clear();
ﻩ ﻩ bp_page();
ﻩﻩﻩ break;
ﻩcase 5:
ﻩﻩ ﻩOLED_clear();
ﻩﻩﻩﻩkal_km_page();
ﻩ ﻩﻩbreak;ﻩﻩ
default:
ﻩﻩ break; ﻩ
ﻩ}
③SPI程序:
SPI 就是一种全双工串行接口,英文全称: Serial Peripheral Interface,可处理多个连接到指定总线上得主机与从机。在数据传输过程中,总线上只能有一个主机与一个从机通信。在数据传输中,主机总就是会向从机发送一帧 8到 16 个位得数据,而从机也总会向主机发送一帧字节数据。“全双工”意义为:主机、从机同时给对方发送数据。 SPI,就是一种高速得,全双工, 同步得通信总线(“同步” 得意思就是数据传输需要时钟线),并且在芯片得管脚上只占用四根线,“信盈达智能穿戴设备开发平台”上得 OLED 屏使用得就是 SPI 接口。
SPI 控制器得初始化步骤有以下几步:
(1) 使能 SPI 复用功能所映射得 GPIO 口时钟。
(2) SPI 控制器时钟使能。
(3) 配置 GPIO 为复用功能。( MOSI/MISO/CLK)
(4) GPIO 复用功能为第几复用功能( AFx)。
(5) 配置 GPIO 输出速率为 50MHz。
(6) 配置 SPIx->CR1 寄存器。
相关代码如下所示:
void Spi1_init(void)
{
ﻩRCC->AHB1ENR |= 1<<1;//PB时钟使能
ﻩRCC->APB2ENR |= 1<<12;//SPI1
/* PB3/4/5 AF5功能 */
GPIOB->MODER &= ~(0X3F << 6);
ﻩGPIOB->MODER |= 0X2A << 6;
ﻩGPIOB->AFR[0] &= ~(0XFFF << 12);
GPIOB->AFR[0] |= 0X555 << 12;// af5功能
ﻩGPIOB->OSPEEDR &= ~(0X3F << 6);// io输出速度 50MHZ
GPIOB->OSPEEDR |= 0X2A << 6;
/* SPI1配置 */
ﻩSPI1->CR1 = 0;
ﻩSPI1->CR1 |= 3 << 8;//SSM SSI
ﻩSPI1->CR1 |= 1 << 2;//主模式
//ﻩSPI1->CR1 |= 4 << 3;//速度 100/64 MHZ
ﻩSPI1->CR1 |= 1 << 6;//使能SPI1
}
u8 Spi1_RevSendByte(u8 val)
{
while ((SPI1->SR & (1<<1)) == 0)
ﻩ{
ﻩﻩ;//等待发送缓存区为空
}
SPI1->DR = val;
ﻩwhile ((SPI1->SR & (1<<0)) == 0)
ﻩ{
;//等待接收缓存区非空
}
ﻩreturn (SPI1->DR);
}
④SHT20芯片程序:
#include "iic、h"
#include "delay、h"
#include "sht20、h"
#define SHT20ADDR 0x80 //SHT20写地址
#define ACK 0 //应答信号
#define NACK 1 //非应答信号
#define FAIL 1 //读取温湿度失败得返回值。
#define READ_TEMP_D 0xf3 //读取温度命令
#define READ_HUMI_D 0xf5 //读取湿度命令
TempHumiValue_t temp_humi_Value;
static void SHT20_setResolution(void);
static void SHT20_setResolution(void);
void SHT20_softReset(void);
static u8 SHT20_writeOneByte(u8 dataToWrite)
{
ﻩu8 ack;
ack = IIC_WriteByte(dataToWrite); //发送字节
return ack;
}
void SHT20_softReset(void)
{
IIC_Start(); //start I2C
ﻩSHT20_writeOneByte(SHT20ADDR&0xfe); //I2C address + write
SHT20_writeOneByte(0xfe); //soft reset
IIC_Stop(); //stop I2C
}
void SHT20_Init(void)
{
SHT20_softReset();
}
static u8 SHT20_readOneByte(u8 ack)
{
u8 temp;
temp=IIC_ReadByte(ack);ﻩ
return temp;
}
static void SHT20_setResolution(void)
{
IIC_Start(); //Start I2C
if(SHT20_writeOneByte(SHT20ADDR&0xfe)==ACK) //I2C address + write + ACK
{
if(SHT20_writeOneByte(0xe6)==ACK) //写用户寄存器
{
if(SHT20_writeOneByte(0x83)==ACK); //设置分辨率 11bit RH% 测量时间:12ms(typ、) & 11bit T℃ 测量时间:9ms(typ、)
}
}
IIC_Stop(); //Stop I2C
}
float SHT20_readTemOrHum(u8 mod)
{
ﻩfloat temp; //温度
ﻩu8 ack=1;
ﻩu8 MSB,LSB; //温度、相对湿度得寄存器数据
ﻩfloat Humidity,Temperature; //温湿度得转换结果
SHT20_setResolution(); //设置帧率8bit,9bit,10 bit,11bit ,12bit,13bit,14bit
IIC_Start(); //iic开始信号
ack = SHT20_writeOneByte(SHT20ADDR&0xfe);
if( ack == ACK ) //写地址,并等待ACK
{
ﻩ if(SHT20_writeOneByte(mod)==ACK) //写命令
ﻩ{
do
ﻩ {
ﻩﻩdelay_ms(6); //延时
IIC_Start(); //发送开始信号
}while(SHT20_writeOneByte(SHT20ADDR|0x01)==NACK); //无应答则整形,还在测量中,如果有应答,则结束当前循环
ﻩMSB = SHT20_readOneByte(ACK); //读Data(MSB),给应答ACK
ﻩLSB = SHT20_readOneByte(ACK); //读Data(LSB),给应答ACK
ﻩSHT20_readOneByte(NACK); //读Checksum ,不给应答NACK
ﻩ ﻩIIC_Stop(); //Stop I2C
ﻩﻩ LSB &= 0xfc; //Data (LSB) 得后两位在进行物理计算前前须置‘0’
ﻩﻩﻩtemp = MSB*256 + LSB; //十六进制转成十进制
ﻩ ﻩif (mod==((u8)READ_HUMI_D)) //命令为读取湿度得命令
{
ﻩ ﻩ/*-- calculate relative humidity [%RH] --*/
ﻩ ﻩHumidity =(temp*125)/65536-6; //公式: RH%= -6 + 125 * SRH/2^16
ﻩ return Humidity; //返回值:humidity
ﻩﻩﻩ}
ﻩﻩﻩelse if(mod==((u8)READ_TEMP_D)) //命令为读取温度得命令
ﻩ {
ﻩﻩﻩ /*-- calculate temperature [°C] --*/
Temperature = (temp*175、72f)/65536-46、85f; //公式:T= -46、85 + 175、72 * ST/2^16
ﻩﻩﻩreturn Temperature; //返回值:temperature
ﻩﻩ}
ﻩ }
}
return FAIL;
}
TempHumiValue_t * SHT20_readTemAndHum(void)
{
temp_humi_Value、humidity = SHT20_readTemOrHum(READ_HUMI_D);//读取湿度
temp_humi_Value、temperature = SHT20_readTemOrHum(READ_TEMP_D);//读取湿度
return &temp_humi_Value; }
⑤OLED初始化程序:
//初始化SSD1306 ﻩ
void Oled_init(void)
{
ﻩOLED_pinInit();ﻩ
OLED_deSelect(); //不选择OLED
ﻩOLED_reset();
ﻩOLED_writeByte(0xAE,OLED_CMD);//--turn off oled panel
OLED_writeByte(0x02,OLED_CMD);//---SET low column address
OLED_writeByte(0x10,OLED_CMD);//---SET high column address
ﻩOLED_writeByte(0x40,OLED_CMD);//--SET start line address SET Mapping RAM Display Start Line (0x00~0x3F)
ﻩOLED_writeByte(0x81,OLED_CMD);//--SET contrast control register
OLED_writeByte(0xCF,OLED_CMD); // SET SEG Output Current Brightness
OLED_writeByte(0xA1,OLED_CMD);//--SET SEG/Column Mapping 0xa0左右反置 0xa1正常
OLED_writeByte(0xC8,OLED_CMD);//SET /Row Scan Direction 0xc0上下反置 0xc8正常
OLED_writeByte(0xA6,OLED_CMD);//--SET normal display
ﻩOLED_writeByte(0xA8,OLED_CMD);//--SET multiplex ratio(1 to 64)
ﻩOLED_writeByte(0x3f,OLED_CMD);//--1/64 duty
ﻩOLED_writeByte(0xD3,OLED_CMD);//-SET display offSET Shift Mapping RAM Counter (0x00~0x3F)
ﻩOLED_writeByte(0x00,OLED_CMD);//-not offSET
OLED_writeByte(0xd5,OLED_CMD);//--SET display clock divide ratio/oscillator frequency
ﻩOLED_writeByte(0x80,OLED_CMD);//--SET divide ratio, SET Clock as 100 Frames/Sec
ﻩOLED_writeByte(0xD9,OLED_CMD);//--SET pre-charge period
OLED_writeByte(0xF1,OLED_CMD);//SET Pre-Charge as 15 Clocks & Discharge as 1 Clock
ﻩOLED_writeByte(0xDA,OLED_CMD);//--SET pins hardware configuration
ﻩOLED_writeByte(0x12,OLED_CMD);
OLED_writeByte(0xDB,OLED_CMD);//--SET vh
OLED_writeByte(0x40,OLED_CMD);//SET V Deselect Level
OLED_writeByte(0x20,OLED_CMD);//-SET Page Addressing Mode (0x00/0x01/0x02)
OLED_writeByte(0x02,OLED_CMD);//
OLED_writeByte(0x8D,OLED_CMD);//--SET Charge Pump enable/disable
OLED_writeByte(0x14,OLED_CMD);//--SET(0x10) disable
OLED_writeByte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)
OLED_writeByte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7)
OLED_writeByte(0xAF,OLED_CMD);//--turn on oled panel
ﻩOLED_writeByte(0xAF,OLED_CMD); /*display ON*/
ﻩOLED_clear();
OLED_setPos(0,0); ﻩ
5 结束语
通过本次为期五天得嵌入式实训,让我对上个学期学习得嵌入式相关只就是有了深一步得了解。通过本次实验,我感觉收获还就是蛮多得。可能我对于嵌入式得知识学习得还就是不太多,但就是这之外得东西收获颇丰。这就就是一个自我学习得过程。当我们通过实验去学习理论知识时,自己动手得出得结论,不仅能加深我们对嵌入式得理解,更能加深我们对此得记忆。
参考文献
[1] 陈志旺、STM32嵌入式微控制器快速上手(第二版)[M]、北京:电子工业出版社,2014、5
[2] 嵌入式系统原理及应用[M]、北京:北京邮电大学出版社,2009
[3] 桑楠、嵌入式系统原理及应用开发技术、 北京:北航大学出版社,2003
附录
电路原理图:
Main、c程序
#include "stm32f4xx、h"
#include "key、h"
#include "led、h"
#include "exti、h"
#include "uart、h"
#include "delay、h"
#include "timer、h"
#include "oled、h"
#include "spi、h"
#include "bmp、h"
#include "iic、h"
#include "sht20、h"
#include "hp6、h"
#include "mpu6050、h"
u8 page = 0;
void clock_page(void);
void pulse_page(void);
void bp_page(void);
void step_page(void);
void kal_km_page(void);
int main()//裸机程序结构
{
ﻩdelay_init(100);
led_init();
key_init();
Spi1_init();
Oled_init();
IIC_PinInit();
ﻩSHT20_Init();
Hp_6_init(); //初始化HP6心率血压 模块
MPU_Init();
//HP_6_VersionInfo();
ﻩwhile (1)
ﻩ{ﻩﻩ
ﻩ switch(page)
ﻩﻩ{
ﻩﻩﻩcase 0:
ﻩ OLED_clear();
ﻩ kal_km_page();ﻩ
case 1:
ﻩ OLED_clear();
ﻩﻩﻩﻩclock_page();
ﻩﻩ break;
ﻩﻩcase 2:
ﻩ OLED_clear();
ﻩ ﻩ pulse_page();
ﻩﻩ ﻩbreak;
case 3:
ﻩﻩ OLED_clear();
ﻩ bp_page();
ﻩﻩﻩ break;
ﻩ default:
ﻩ break; ﻩﻩ
ﻩ}
}
}
void kal_km_page (void)
{
ﻩwhile(1)
{
ﻩ OLED_showCHinese(0, 0, 0);
ﻩ OLED_showCHinese(16, 0, 1);
ﻩ OLED_showCHinese(32, 0, 2);
ﻩ OLED_showCHinese(48, 0, 3);
ﻩﻩOLED_showCHinese(64, 0, 4);
OLED_showCHinese(80, 0, 5);
ﻩﻩ OLED_showCHinese(0, 2, 6);
ﻩﻩOLED_showCHinese(16, 2, 7);
ﻩOLED_showCHinese(32, 2, 8);
ﻩﻩOLED_showCHinese(48, 2, 9);
OLED_showCHinese(64, 2, 10);
ﻩ ﻩOLED_showCHinese(80, 2, 11);
ﻩﻩif(key_scan())
{
ﻩ ﻩpage = page +1; //切换到page1
ﻩ IIC_Stop();
ﻩﻩbreak; //跳出当前页面
}ﻩﻩﻩ
}
}
void clock_page(void)
{
TempHumiValue_t humi_temp_val ; //温湿度ﻩ
u8 uiBuf[40];
while(1)
{
ﻩﻩhumi_temp_val = *SHT20_readTemAndHum();//获取温度
ﻩ sprintf((char*)uiBuf,"%02dc %02d",(char)humi_temp_val、temperature,(char)humi_temp_val、humidity); // 以整数显示
ﻩﻩOLED_showString(10,6,uiBuf,16); ﻩ
ﻩ OLED_showString(10+8*7,6,"%",16);
ﻩ if(key_scan())
ﻩﻩ{
page = page +1; //切换到page1
ﻩ IIC_Stop();
ﻩ break; //跳出当前页面
} ﻩﻩ
ﻩ}
}
void pulse_page(void)
{
static u8 oldPulseVal = 0; //上一次得心率值
u8 uiBuf[40];
u8 pulseBuf[24] = {0};
HP_6_OpenRate(); //打开心率测量
OLED_showString(10,4,"pulse",16);
while(1)
ﻩ{ﻩ
// OLED_showString(10,4,"pulse",16);
// HP_6_GetRateResult();
//ﻩﻩHP_6_GetResultData(pulseBuf);
// ﻩ
//ﻩ sprintf((char*)uiBuf,"%03d",pulseBuf[7]); // //byte 7就是心率结果
// ﻩOLED_showString(10,6,uiBuf,16); ﻩ
// ﻩdelay_ms(100);
ﻩﻩif(pulseBuf[7] && pulseBuf[7]!= oldPulseVal) //如果可以获得心率结果,表明测量成功,则关闭心率测量
ﻩ{
ﻩﻩﻩoldPulseVal = pulseBuf[7];
ﻩ HP_6_CloseRate();
ﻩﻩ sprintf((char*)uiBuf,"%03d",pulseBuf[7]); // //byte 7就是心率结果
ﻩﻩOLED_showString(10,6,uiBuf,16);
}
else //如果获取不到心率结果,则每隔100毫秒钟获取心率值
{
HP_6_GetRateResult();
ﻩ HP_6_GetResultData(pulseBuf);
ﻩﻩdelay_ms(100);
ﻩ }
ﻩif(key_scan())
ﻩﻩ{
ﻩﻩﻩpage = page +1; //切换到page2
ﻩﻩHP_6_CloseRate(); //关闭心率测量
ﻩﻩIIC_Stop();
ﻩ break; //跳出当前页面
}ﻩ
}
}
void bp_page(void)
{
ﻩu8 uiBuf[40];
u8 BpBuf[24] = {0};
HP_6_OpenBp(); //打开血压测量
while(1)
ﻩ{
HP_6_GetBpResult(); //获取血压测量状态
HP_6_GetResultData(BpBuf);
if(0 == BpBuf[7]) //byte 7就是血压测量得状态:0测量中,1测量完成、2测量失败
ﻩ OLED_showString(10,4,"testing",16);
else if(1 == BpBuf[7])
{
ﻩﻩOLED_showString(10,4,"success",16);
ﻩsprintf((char*)uiBuf,"%03d/%03d MMGH", BpBuf[10], BpBuf[11]);//byte 10就是血压测量结果得高压,byte 11就是血压测量结果得低压ﻩ
ﻩOLED_showString(10,6,uiBuf,16);
HP_6_CloseBp();
ﻩ }ﻩﻩ
else if(2 == BpBuf[7])
{
ﻩﻩ HP_6_CloseBp();
OLED_showString(10,4,"fail ",16);ﻩﻩ
} ﻩ
else
//do nothing
ﻩ delay_ms(100);
if(key_scan())
ﻩ {
ﻩ page =0; //切换到page3
ﻩ HP_6_CloseBp(); //关闭血压测量
ﻩ IIC_Stop();
ﻩﻩ break; //跳出当前页面
}ﻩ
}
}
展开阅读全文