完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
任务要求
练习通过SPI总线实现OLED屏幕显示。显示自己的学号和姓名。 显示AHT20的温度和湿度; 上下或左右的滑动显示长字符; 本人所用开发板:野火STM32F103指南者; 代码编写烧录:KEIL5 所用协议:SPI; SPI协议接口 SPI协议(SerialPeripheralInterface),即串行外围设备接口,是一种高速全双工的通信总线。 基本通信过程: SPI接口位置: SPI引脚: MISO:主设备输入/从设备输出引脚。该引脚在从模式下发送数据,在主模式下接收数据; MOSI:主设备输出/从设备输入引脚。该引脚在主模式下发送数据,在从模式下接收数据; SCK:串口时钟,作为主设备的输入,从设备的输入; NSS:从设备选择。这是一个可选的引脚,用来选择主/从设备。它的功能是用来作为“片选引脚”,让主设备可以单独地与特定从设备通讯,避免数据线上的冲突。 SPI下的STM32与OLED连接 显示文本 1.在OLED官网下载例程: 下载完成解压后再用KEIL打开SPI对应的OLED显示例程“0.96inch_OLED_Demo_STM32F103ZET6_Hardware_4-wire_SPI”,如下: 2.STM32与OLED的连接依据main.c程序里的注释提示进行连接即可,如下: 注意:此时的OLED的CS接口不用连接,只需要六根线进行STM32与OLED的连接。 完成后,模块显示如下: 此时直接编译烧录例程,不用改动,显示如下: 此时如果OLED屏不显示,可能是接线有问题,检查即可。 3.改写程序: 在oledfont.h头文件里添加个人需要显示的汉字字模,此时需要利用PCtoLCD软件,打开界面如下: 该软件为野火资料包里的开发软件自带。 关于字模软件的使用详见野火自带教程。 此时选取字模,添加进数组。如下: const typFNT_GB16 cfont16[] = { “马”,0x00,0x00,0x7F,0xE0,0x00,0x20,0x00,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x1F,0xFC, 0x00,0x04,0x00,0x04,0x00,0x04,0xFF,0xE4,0x00,0x04,0x00,0x04,0x00,0x28,0x00,0x10,/*“妈”,0*/ “舒”,0x10,0x00,0x11,0xF8,0x28,0x08,0x44,0x50,0x82,0x20,0x7C,0x10,0x13,0xFE,0x10,0x22, 0xFE,0x24,0x10,0x20,0x10,0x20,0x7C,0x20,0x44,0x20,0x44,0x20,0x7C,0xA0,0x44,0x40,/*“舒”,0*/ “娅”,0x20,0x00,0x23,0xFC,0x20,0x90,0x20,0x90,0xF8,0x90,0x48,0x92,0x4C,0x92,0x4A,0x94, 0x8A,0x94,0x4A,0x98,0x30,0x90,0x10,0x90,0x28,0x90,0x48,0x90,0x87,0xFE,0x00,0x00,/*“娅”,0*/ 注意:此时我选择的是1616的OLED汉字显示,因此在添加字模时,也是添加进1616汉字显示对应的数组。添加后注意保存。 再进入test.c进行修改,将void TEST_MainPage(void)函数修改。如下: void TEST_MainPage(void) { GUI_ShowString(20,0,“631807030324”,8,1); GUI_ShowCHinese(16,20,16,“马舒娅”,1); delay_ms(1500); } 修改完成,再进入main.c文件进行修改,如下: #include “delay.h” #include “sys.h” #include “oled.h” #include “gui.h” #include “test.h” int main(void) { delay_init(); //延时函数初始化 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIc中断分组2:2位抢占优先级,2位响应优先级 OLED_Init(); //初始化OLED OLED_Clear(0); //清屏,全黑 while(1) { TEST_MainPage(); //主页面显示姓名与学号 OLED_Clear(0); } } 此时全部程序已修改完毕,现在进行编译烧录,即可成功运行。 显示温湿度与文本的滚动显示 前提是利用I2C已经做出了基于STM32与AHT20的温湿度检测。 温湿度显示 1,在上文中的例程里加入之前测量温湿度的文件与头文件; 如下: 2,需要在主程序main()中加入读取温湿度的函数,如下: void read_AHT20_once(void) { delay_ms(10); reset_AHT20(); delay_ms(10); init_AHT20(); delay_ms(10); startMeasure_AHT20(); delay_ms(80); read_AHT20(); delay_ms(5); } 3,读取在OLED显示温湿度,如下: void reset_AHT20(void) { //Êý¾Ý´«Ê俪ʼÐźŠI2C_Start(); //·¢ËÍÊý¾Ý I2C_WriteByte(0x70); //½ÓÊÕ ACK ÐźŠack_status = Receive_ACK(); //·¢ËÍÈí¸´Î»ÃüÁÖØÆô´«¸ÐÆ÷ϵͳ£© I2C_WriteByte(0xBA); //½ÓÊÕ ACK ÐźŠack_status = Receive_ACK(); //Í£Ö¹ I2C ÐÒé I2C_Stop(); } //0x70 ¡ª》 0111 0000 Ç°Æßλ±íʾ I2C µØÖ·£¬µÚ°ËλΪ0£¬±íʾ write //0xE1 ¡ª》 ¿´×´Ì¬×ÖµÄУ׼ʹÄÜλBit[3]ÊÇ·ñΪ 1 //0x08 0x00 ¡ª》 0xBE ÃüÁîµÄÁ½¸ö²ÎÊý£¬Ïê¼û AHT20 ²Î¿¼ÊÖ²á void init_AHT20(void) { //´«Ê俪ʼ I2C_Start(); //дÈë 0x70 Êý¾Ý I2C_WriteByte(0x70); //½ÓÊÕ ACK ÐźŠack_status = Receive_ACK(); //дÈë 0xE1 Êý¾Ý I2C_WriteByte(0xE1); ack_status = Receive_ACK(); //дÈë 0x08 Êý¾Ý I2C_WriteByte(0x08); ack_status = Receive_ACK(); //дÈë 0x00 Êý¾Ý I2C_WriteByte(0x00); ack_status = Receive_ACK(); //Í£Ö¹ I2C ÐÒé I2C_Stop(); } //0x70 ¡ª》 0111 0000 Ç°Æßλ±íʾ I2C µØÖ·£¬µÚ°ËλΪ0£¬±íʾ write //0xAC ¡ª》 ´¥·¢²âÁ¿ //0x33 0x00 ¡ª》 0xAC ÃüÁîµÄÁ½¸ö²ÎÊý£¬Ïê¼û AHT20 ²Î¿¼ÊÖ²á void startMeasure_AHT20(void) { //Æô¶¯ I2C ÐÒé I2C_Start(); I2C_WriteByte(0x70); ack_status = Receive_ACK(); I2C_WriteByte(0xAC); ack_status = Receive_ACK(); I2C_WriteByte(0x33); ack_status = Receive_ACK(); I2C_WriteByte(0x00); ack_status = Receive_ACK(); I2C_Stop(); } void read_AHT20(void) { uint8_t i; //³õʼ»¯ readByte Êý×é for(i=0; i《6; i++) { readByte[i]=0; } I2C_Start(); //ͨ¹ý·¢ËÍ 0x71 ¿ÉÒÔ»ñÈ¡Ò»¸ö×Ö½ÚµÄ״̬×Ö I2C_WriteByte(0x71); ack_status = Receive_ACK(); //½ÓÊÕ 6 ¸ö 8 bitµÄÊý¾Ý readByte[0]= I2C_ReadByte(); //·¢ËÍ ACK ÐźŠSend_ACK(); readByte[1]= I2C_ReadByte(); Send_ACK(); readByte[2]= I2C_ReadByte(); Send_ACK(); readByte[3]= I2C_ReadByte(); Send_ACK(); readByte[4]= I2C_ReadByte(); Send_ACK(); readByte[5]= I2C_ReadByte(); //·¢ËÍ NACK ÐźŠSendNot_Ack(); I2C_Stop(); //ÎÂʪ¶ÈµÄ¶þ½øÖÆÊý¾Ý´¦Àí //0x68 = 0110 1000 //0x08 = 0000 1000 if( (readByte[0] & 0x68) == 0x08 ) { H1 = readByte[1]; //H1 ×óÒÆ 8 λ²¢Óë readByte[2] Ïà»ò H1 = (H1《《8) | readByte[2]; H1 = (H1《《8) | readByte[3]; //H1 ÓÒÒÆ 4 λ H1 = H1》》4; H1 = (H1*1000)/1024/1024; T1 = readByte[3]; //ÓëÔËËã T1 = T1 & 0x0000000F; T1 = (T1《《8) | readByte[4]; T1 = (T1《《8) | readByte[5]; T1 = (T1*2000)/1024/1024 - 500; AHT20_OutData[0] = (H1》》8) & 0x000000FF; AHT20_OutData[1] = H1 & 0x000000FF; AHT20_OutData[2] = (T1》》8) & 0x000000FF; AHT20_OutData[3] = T1 & 0x000000FF; } else { AHT20_OutData[0] = 0xFF; AHT20_OutData[1] = 0xFF; AHT20_OutData[2] = 0xFF; AHT20_OutData[3] = 0xFF; } /* printf(“Íê³É£¡n”); printf(“----ζÈ:%d%d.%d ¡ãCn”,T1/100,(T1/10)%10,T1%10); printf(“----ʪ¶È:%d%d.%d %%”,H1/100,(H1/10)%10,H1%10); printf(“nn”); */ Show_OLED(); } //ת»¯×Ö·û´®Êä³öµ½ OLED ÉÏ void Show_OLED(void) { t = T1/100; switch(t) { case 0:break; case 1:strTemp1 = “1”;break; case 2:strTemp1 = “2”;break; case 3:strTemp1 = “3”;break; case 4:strTemp1 = “4”;break; case 5:strTemp1 = “5”;break; case 6:strTemp1 = “6”;break; case 7:strTemp1 = “7”;break; case 8:strTemp1 = “8”;break; case 9:strTemp1 = “9”;break; } t = (T1/10)%10; switch(t) { case 0:strTemp2 = “0”;break; case 1:strTemp2 = “1”;break; case 2:strTemp2 = “2”;break; case 3:strTemp2 = “3”;break; case 4:strTemp2 = “4”;break; case 5:strTemp2 = “5”;break; case 6:strTemp2 = “6”;break; case 7:strTemp2 = “7”;break; case 8:strTemp2 = “8”;break; case 9:strTemp2 = “9”;break; } t = T1%10; switch(t) { case 0:strTemp3 = “0”;break; case 1:strTemp3 = “1”;break; case 2:strTemp3 = “2”;break; case 3:strTemp3 = “3”;break; case 4:strTemp3 = “4”;break; case 5:strTemp3 = “5”;break; case 6:strTemp3 = “6”;break; case 7:strTemp3 = “7”;break; case 8:strTemp3 = “8”;break; case 9:strTemp3 = “9”;break; } t = H1/100; switch(t) { case 0:break; case 1:strHumi1 = “1”;break; case 2:strHumi1 = “2”;break; case 3:strHumi1 = “3”;break; case 4:strHumi1 = “4”;break; case 5:strHumi1 = “5”;break; case 6:strHumi1 = “6”;break; case 7:strHumi1 = “7”;break; case 8:strHumi1 = “8”;break; case 9:strHumi1 = “9”;break; } t = H1/100; switch(t) { case 0:strHumi2 = “0”;break; case 1:strHumi2 = “1”;break; case 2:strHumi2 = “2”;break; case 3:strHumi2 = “3”;break; case 4:strHumi2 = “4”;break; case 5:strHumi2 = “5”;break; case 6:strHumi2 = “6”;break; case 7:strHumi2 = “7”;break; case 8:strHumi2 = “8”;break; case 9:strHumi2 = “9”;break; } t = H1/100; switch(t) { case 0:strHumi3 = “0”;break; case 1:strHumi3 = “1”;break; case 2:strHumi3 = “2”;break; case 3:strHumi3 = “3”;break; case 4:strHumi3 = “4”;break; case 5:strHumi3 = “5”;break; case 6:strHumi3 = “6”;break; case 7:strHumi3 = “7”;break; case 8:strHumi3 = “8”;break; case 9:strHumi3 = “9”;break; } GUI_ShowString(40,32,“ ”,16,1); GUI_ShowString(40,48,“ ”,16,1); GUI_ShowCHinese(0,32,16,“ζȣº”,1); GUI_ShowString(40,32,strTemp1,16,1); GUI_ShowString(48,32,strTemp2,16,1); GUI_ShowString(56,32,“。”,16,1); GUI_ShowString(64,32,strTemp3,16,1); GUI_ShowCHinese(72,32,16,“¡æ”,1); GUI_ShowCHinese(0,48,16,“ʪ¶È£º”,1); GUI_ShowString(40,48,strHumi1,16,1); GUI_ShowString(48,48,strHumi2,16,1); GUI_ShowString(56,48,“。”,16,1); GUI_ShowString(64,48,strHumi3,16,1); GUI_ShowCHinese(72,48,16,“£¥”,1); } 文本滚动显示 1,在上文中的例程里加入水平滚动的·函数,如下: OLED_WR_Byte(0x2E,OLED_CMD); OLED_WR_Byte(0x27,OLED_CMD); OLED_WR_Byte(0x00,OLED_CMD); OLED_WR_Byte(0x00,OLED_CMD); OLED_WR_Byte(0x07,OLED_CMD); OLED_WR_Byte(0x01,OLED_CMD); OLED_WR_Byte(0x00,OLED_CMD); OLED_WR_Byte(0xFF,OLED_CMD); TEST_xianshi(); OLED_WR_Byte(0x2F,OLED_CMD); 2,滚动显示“欢迎来到冬天”,将字模加入到数组,如下: “欢”,0x00,0x80,0x00,0x80,0xFC,0x80,0x04,0xFC,0x05,0x04,0x49,0x08,0x2A,0x40,0x14,0x40, 0x10,0x40,0x28,0xA0,0x24,0xA0,0x45,0x10,0x81,0x10,0x02,0x08,0x04,0x04,0x08,0x02, “迎”,0x00,0x00,0x20,0x80,0x13,0x3C,0x12,0x24,0x02,0x24,0x02,0x24,0xF2,0x24,0x12,0x24, 0x12,0x24,0x12,0xB4,0x13,0x28,0x12,0x20,0x10,0x20,0x28,0x20,0x47,0xFE,0x00,0x00, “来´”,0x01,0x00,0x01,0x00,0x01,0x00,0x7F,0xFC,0x01,0x00,0x11,0x10,0x09,0x10,0x09,0x20, 0xFF,0xFE,0x03,0x80,0x05,0x40,0x09,0x20,0x31,0x18,0xC1,0x06,0x01,0x00,0x01,0x00, “到”,0x00,0x04,0xFF,0x84,0x08,0x04,0x10,0x24,0x22,0x24,0x41,0x24,0xFF,0xA4,0x08,0xA4, 0x08,0x24,0x08,0x24,0x7F,0x24,0x08,0x24,0x08,0x04,0x0F,0x84,0xF8,0x14,0x40,0x08, “冬”,0x04,0x00,0x04,0x00,0x0F,0xF0,0x10,0x10,0x28,0x20,0x44,0x40,0x03,0x80,0x0C,0x60, 0x30,0x18,0xC0,0x06,0x07,0x00,0x00,0xC0,0x00,0x20,0x0E,0x00,0x01,0x80,0x00,0x40, “天”,0x00,0x00,0x3F,0xF8,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xFF,0xFE,0x01,0x00, 0x02,0x80,0x02,0x80,0x04,0x40,0x04,0x40,0x08,0x20,0x10,0x10,0x20,0x08,0xC0,0x06, 总结 本次STM32 SPI协议接口下的OLED屏显示主要任务已完成,对于STM32的SPI接口协议的学习还需更加深入。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1804 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1629 浏览 1 评论
1097 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
736 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1686 浏览 2 评论
1944浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
748浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
582浏览 3评论
604浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
565浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-28 20:13 , Processed in 0.834257 second(s), Total 76, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (威廉希尔官方网站 图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号