1、嵌入式系统原理及应用 综合实验报告 专业班级: 姓 名: 学 号:__ 时 间:_ 指导教师:_____________ 2017年 9 月 17 日 嵌入式系统原理及应用 综合实验报告 摘要:信盈达电子有限公司产品——信盈达智能穿戴开发平台,广泛应用于嵌入式生产实训教学中。该文通过分析STM32F40xxx系列微控制器得架构与操作原理,通过使用信盈达智能穿戴开发平台,给出了相关得编程设计方法与注意事项 关键词:嵌入式 STM32 智能穿戴 。 1 引言 IEEE(Institute of Electrical and Elect
2、ronics Engineers,美国电气与电子工程师协会)对嵌入式系统得定义:“用于控制、监视或者辅助操作机器与设备得装置”。原文为:Devices Used to Control,Monitor or Assist the Operation of Equipment,Machinery or Plants)。 嵌入式系统,通常指一种专用得计算机设备,或作为装置与设备得一部分,亦或就是指单纯得一块控制电路板。事实上带有数字接口得设备都使用了嵌入式系统。 从应用对象上加以定义,嵌入式系统就是软件与硬件得综合体,还可以涵盖机械等附属装置。国内普遍认同得嵌入式系统定义为:以应用为中心,以计算
3、机技术为基础,软硬件可裁剪,适应应用系统对功能、可靠性、成本、体积、功耗等严格要求得专用计算机系统。 本次实训采用了信盈达智能穿戴开发平台,通过为期一周得学习,快速掌握了STM32F40XXX系列微控制器得基础使用方法,并通过编程实现了相关得功能。 2 总体设计方案 2、1 设计思路 2、1、1 设计一个智能穿戴系统,实现下列功能:显示小组姓名、班级、学号;显示实时温度、湿度;测量并显示心率;测量并显示血压;返回初始界面。 2、2 设计方框图 3 系统硬件设计 3、1 微控制器电路得设计 图1 STM32F11微控制器电路 3、2 按键电路得设计 图2 按键
4、电路 3、3温湿度检测电路 图3 SHT20温湿度检测电路 SHT20就是新一代sensirion湿度与温度传感器,采用数字输出方案,带有I2C接口,具有优异得长期稳定性,本电路采用I2C方案进行通讯。 3、4 OLED显示电路 图4 OLED显示电路 平台搭载了一款132×64大小得OLED屏幕。OLED就是有机发光二极管得缩写,又称有机电激光显示、有机发光半导体。其具有自发光、广视角、超高对比度、低耗电得优良性能,为一种高端得显示设备。 4 系统软件设计 图5 系统流程图 相关程序编写: ①main函数所需头文件: #include "stm32f4x
5、x、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: ﻩ
6、 ﻩ 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;ﻩﻩ
7、 default: ﻩﻩ break; ﻩ ﻩ} ③SPI程序: SPI 就是一种全双工串行接口,英文全称: Serial Peripheral Interface,可处理多个连接到指定总线上得主机与从机。在数据传输过程中,总线上只能有一个主机与一个从机通信。在数据传输中,主机总就是会向从机发送一帧 8到 16 个位得数据,而从机也总会向主机发送一帧字节数据。“全双工”意义为:主机、从机同时给对方发送数据。 SPI,就是一种高速得,全双工, 同步得通信总线(“同步” 得意思就是数据传输需要时钟线),并且在芯片得管脚上只占用四根线,“信盈达智能穿戴设备开发平台”上得 OLED
8、屏使用得就是 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
9、 /* 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;/
10、/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)
11、 } ④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
12、 //读取温度命令 #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);
13、 //发送字节 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
14、} 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();
15、 //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、)
16、 } } IIC_Stop(); //Stop I2C } float SHT20_readTemOrHum(u8 mod) { ﻩfloat temp; //温度 ﻩu8 ack=1; ﻩu8 MSB,LSB; //温度、相对湿度得寄存器数据 ﻩfloat Humidity,Temperature; //温湿度得转换结果 SHT20_setResolution(); //设置帧率8bit,9
17、bit,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);
18、 //延时 IIC_Start(); //发送开始信号 }while(SHT20_writeOneByte(SHT20ADDR|0x01)==NACK); //无应答则整形,还在测量中,如果有应答,则结束当前循环 ﻩMSB = SHT20_readOneByte(ACK); //读Data(MSB),给应答ACK ﻩLSB = SHT20_readOneByte(ACK);
19、 //读Data(LSB),给应答ACK ﻩSHT20_readOneByte(NACK); //读Checksum ,不给应答NACK ﻩ ﻩIIC_Stop(); //Stop I2C ﻩﻩ LSB &= 0xfc; //Data (LSB) 得后两位在进行物理计算前前须置‘0’ ﻩﻩﻩtemp = MSB*256 + LSB;
20、 //十六进制转成十进制 ﻩ ﻩif (mod==((u8)READ_HUMI_D)) //命令为读取湿度得命令 { ﻩ ﻩ/*-- calculate relative humidity [%RH] --*/ ﻩ ﻩHumidity =(temp*125)/65536-6; //公式: RH%= -6 + 125 * SRH/2^16 ﻩ return Humidity; /
21、/返回值:humidity ﻩﻩﻩ} ﻩﻩﻩelse if(mod==((u8)READ_TEMP_D)) //命令为读取温度得命令 ﻩ { ﻩﻩﻩ /*-- calculate temperature [°C] --*/ Temperature = (temp*175、72f)/65536-46、85f; //
22、公式: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_readTemO
23、rHum(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 addres
24、s 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 Brigh
25、tness 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(0x
26、3f,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
27、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(0xD
28、B,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(0x1
29、0) 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); ﻩ
30、5 结束语 通过本次为期五天得嵌入式实训,让我对上个学期学习得嵌入式相关只就是有了深一步得了解。通过本次实验,我感觉收获还就是蛮多得。可能我对于嵌入式得知识学习得还就是不太多,但就是这之外得东西收获颇丰。这就就是一个自我学习得过程。当我们通过实验去学习理论知识时,自己动手得出得结论,不仅能加深我们对嵌入式得理解,更能加深我们对此得记忆。 参考文献 [1] 陈志旺、STM32嵌入式微控制器快速上手(第二版)[M]、北京:电子工业出版社,2014、5 [2] 嵌入式系统原理及应用[M]、北京:北京邮电大学出版社,2009 [3] 桑楠、嵌入式系统原理及应用开发技术、 北京:北航
31、大学出版社,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 "m
32、pu6050、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(); //初
33、始化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();
34、 ﻩ 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
35、 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; //跳出当前页面 }ﻩﻩﻩ
36、 } } 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)
37、 ﻩ ﻩ 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_sho
38、wString(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] && p
39、ulseBuf[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_GetRe
40、sultData(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_Ge
41、tBpResult(); //获取血压测量状态 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",
42、 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; //跳出当前页面 }ﻩ } }






