晶联讯JLX12864G-290液晶,STM32+HAL库 SPI显示成功。

 

 


JLX12864G_290_PN.h

#ifndef __JLX12864G_290_PN_H__
#define __JLX12864G_290_PN_H__

/* 包含头文件 ----------------------------------------------------------------*/
#include "stm32f0xx_hal.h"

/* 类型定义 --------------------------------------------------------------*/
#define CS_H          HAL_GPIO_WritePin(CS_GPIO_Port,CS_Pin,GPIO_PIN_SET) // 输出高电平
#define CS_L          HAL_GPIO_WritePin(CS_GPIO_Port,CS_Pin,GPIO_PIN_RESET) // 输出低电平
#define RST_H         HAL_GPIO_WritePin(RST_GPIO_Port,RST_Pin,GPIO_PIN_SET) // 输出高电平
#define RST_L         HAL_GPIO_WritePin(RST_GPIO_Port,RST_Pin,GPIO_PIN_RESET) // 输出低电平
#define RS_H          HAL_GPIO_WritePin(RS_GPIO_Port,RS_Pin,GPIO_PIN_SET) // 输出高电平
#define RS_L          HAL_GPIO_WritePin(RS_GPIO_Port,RS_Pin,GPIO_PIN_RESET) // 输出低电平

/* 宏定义 --------------------------------------------------------------------*/


/* 扩展变量 ------------------------------------------------------------------*/
/* 函数声明 ------------------------------------------------------------------*/
//void delay(int i); 
void delay_us(uint8_t i); 
void transfer_command(uint8_t data1);
void transfer_data(uint8_t data1);
void initial_lcd(void);
void lcd_address(uint8_t page,uint8_t column);
void clear_screen(void);
void full_display(uint8_t data_left,uint8_t data_right);
void display_graphic_32x32(uint8_t page,uint8_t column,uint8_t *dp);
void display_graphic_16x16(uint8_t page,uint8_t column,uint8_t reverse,uint8_t *dp);
void display_graphic_8x16(uint8_t page,uint8_t column,uint8_t *dp);
void display_string_8x16(uint16_t page,uint16_t column,uint8_t *text);
void display_string_5x7(uint16_t page,uint16_t column,uint8_t *text);
void disp_grap(uint8_t page,uint8_t column,uint8_t *dp);
#endif  // __JLX12864G_290_PN_H__
 


JLX12864G_290_PN.c

#include "spi.h"
#include "JLX12864G_290_PN/JLX12864G_290_PN.H"


uint8_t ascii_table_8x16[95][16]; 
uint8_t ascii_table_5x7[95][5]; 

///*延时*/ 
//void delay(int i) 
//{ 
// int j,k; 
// for(j=0;j<i;j++) 
// for(k=0;k<110;k++); 
//} 
/*延时*/ 
void delay_us(uint8_t i) 

 int j,k; 
 for(j=0;j<i;j++) 
 for(k=0;k<1;k++); 

//void waitkey() 
//{ 
//  repeat: 
//    if(key==1) 
//      goto repeat; 
//    else 
//      HAL_Delay(1000);
     delay(1000); 
//}

/*写指令到 LCD 模块*/ 
void transfer_command(uint8_t data1) 

   CS_L; 
   RS_L; 
   HAL_SPI_Transmit(&hspi1,&data1,1,0xff);
   CS_H; 

/*写数据到 LCD 模块*/ 
void transfer_data(uint8_t data1) 

   CS_L;
   RS_H;  
   HAL_SPI_Transmit(&hspi1,&data1,1,0xff);
   CS_H; 

/*LCD 模块初始化*/ 
void initial_lcd(void) 

//   CS_L;
   RST_L; /*低电平复位*/ 
   HAL_Delay(100); 
   RST_H; /*复位完毕*/ 
   HAL_Delay(100);  
   transfer_command(0xe2); /*软复位*/ 
   HAL_Delay(5);  
   transfer_command(0x2c); /*升压步聚 1*/ 
   HAL_Delay(5); 
   transfer_command(0x2e); /*升压步聚 2*/ 
   HAL_Delay(5); 
   transfer_command(0x2f); /*升压步聚 3*/ 
   HAL_Delay(5); 
   transfer_command(0x24); /*粗调对比度,可设置范围 0x20~0x27*/ 
   transfer_command(0x81); /*微调对比度*/ 
   transfer_command(0x2a); /*0x1a,微调对比度的值,可设置范围 0x00~0x3f*/ 
   transfer_command(0xa2); /*1/9 偏压比(bias)*/ 
   transfer_command(0xc8); /*行扫描顺序:从上到下*/ 
   transfer_command(0xa0); /*列扫描顺序:从左到右*/ 
   transfer_command(0x40); /*起始行:第一行开始*/ 
   transfer_command(0xaf); /*开显示*/ 
//   CS_H;

void lcd_address(uint8_t page,uint8_t column) 

   column=column-1; //我们平常所说的第 1 列,在 LCD 驱动 IC 里是第 0 列。所以在这里减去 1. 
   page=page-1; 
   transfer_command(0xb0+page); //设置页地址。每页是 8 行。一个画面的 64 行被分成 8 个页。我们平常所说的第 1 页,在 LCD驱动 IC 里是第 0 页,所以在这里减去 1*/ 
   transfer_command(((column>>4)&0x0f)+0x10); //设置列地址的高 4 位 
   transfer_command(column&0x0f); //设置列地址的低 4 位 

/*全屏清屏*/ 
void clear_screen(void) 

   uint8_t i,j; 
   for(i=0;i<9;i++) 
   { 
     lcd_address(1+i,1); 
     for(j=0;j<132;j++) 
     { 
        transfer_data(0x00); 
     } 
   } 

//==================display a piture of 128*64 dots================ 
void full_display(uint8_t data_left,uint8_t data_right) 

   int i,j; 
   for(i=0;i<8;i++) 
   { 
     CS_L; 
     lcd_address(i+1,1); 
     for(j=0;j<64;j++) 
     { 
       transfer_data(data_left); 
       transfer_data(data_right); 
     } 
   } 

/*显示 32x32 点阵图像、汉字、生僻字或 32x32 点阵的其他图标*/ 
void display_graphic_32x32(uint8_t page,uint8_t column,uint8_t *dp) 

   uint8_t i,j; 
   for(j=0;j<4;j++) 
   { 
     lcd_address(page+j,column); 
     for (i=0;i<31;i++) 
     { 
       transfer_data(*dp); /*写数据到 LCD,每写完一个 8 位的数据后列地址自动加 1*/ 
       dp++; 
     } 
   } 

/*显示 16x16 点阵图像、汉字、生僻字或 16x16 点阵的其他图标*/ 
void display_graphic_16x16(uint8_t page,uint8_t column,uint8_t reverse,uint8_t *dp) 

   uint8_t i,j; 
   for(j=0;j<2;j++) 
   { 
     lcd_address(page+j,column); 
     for (i=0;i<16;i++) 
     { 
       if(reverse==1) 
       { 
          transfer_data(*dp); /*写数据到 LCD,每写完一个 8 位的数据后列地址自动加 1*/ 
       } 
       else 
          transfer_data(~*dp); 
       dp++; 
     } 
   } 

/*显示 8x16 点阵图像、ASCII, 或 8x16 点阵的自造字符、其他图标*/ 
void display_graphic_8x16(uint8_t page,uint8_t column,uint8_t *dp) 

   uint8_t i,j; 
   for(j=0;j<2;j++) 
   { 
     lcd_address(page+j,column); 
     for (i=0;i<8;i++) 
     { 
       transfer_data(*dp); /*写数据到 LCD,每写完一个 8 位的数据后列地址自动加 1*/ 
       dp++; 
     } 
   } 

void display_string_8x16(uint16_t page,uint16_t column,uint8_t *text) 

   uint16_t i=0,j,k,n; 
   while(text[i]>0x00) 
   { 
      if((text[i]>=0x20)&&(text[i]<=0x7e)) 
       { 
         j=text[i]-0x20; 
         for(n=0;n<2;n++) 
         { 
           lcd_address(page+n,column); 
           for(k=0;k<8;k++) 
           { 
              transfer_data(ascii_table_8x16[j][k+8*n]);/*显示 5x7 的 ASCII 字到 LCD 上,y 为页地址,x 为列地址,最后为数据*/ 
           } 
         } 
         i++; 
         column+=8;        
       } 
       else 
         i++; 
   } 


void display_string_5x7(uint16_t page,uint16_t column,uint8_t *text) 

   uint16_t i=0,j,k; 
   while(text[i]>0x00) 
   { 
     if((text[i]>=0x20)&&(text[i]<0x7e)) 
     { 
       j=text[i]-0x20; 
       lcd_address(page,column); 
       for(k=0;k<5;k++) 
       { 
          transfer_data(ascii_table_5x7[j][k]);/*显示 5x7 的 ASCII 字到 LCD 上,y 为页地址,x 为列地址,最后为数据*/ 
       } 
       i++; 
       column+=6; 
     } 
     else 
     i++; 
   } 

//==================display a piture of 128*64 dots================ 
void disp_grap(uint8_t page,uint8_t column,uint8_t *dp) 

   int i,j; 
   for(i=0;i<8;i++) 
   { 
     lcd_address(page+i,column); 
     for(j=0;j<128;j++) 
     { 
       transfer_data(*dp); 
       dp++; 
     } 
   } 

 


在main.C中

#include "stm32f10x.h" // Device header #include "delay.h" #include "OLED.h" #include "dht11.h" #include "Serial.h" #include "FAN.h" #include "math.h" /*#include "adc.h" #include "soil_moisture.h"*/ #define TEMP_THRESHILD 28 #define HUMI_THRESHILD 60 u8 temp,humi; static float filtered_temp = 0.0; static float last_display_temp = 0.0; int main(void) { uint32_t bufe[5]; OLED_Init(); DHT11_Init(); Fan_Init(); /*ADC1_Init(); SoilMoisture_Init();*/ OLED_ShowChinese(0, 0, "温度:"); OLED_ShowChinese(94, 0, "℃"); OLED_ShowChinese(0, 16, "湿度:"); /*OLED_ShowChinese(0, 48, "土壤:");*/ OLED_ShowChinese(0, 32, "光照强度:"); OLED_ShowString(94,16,"RH",OLED_8X16); /*OLED_ShowString(40,48," %",OLED_8X16);*/ OLED_ShowString(112,32,"LX",OLED_8X16); OLED_Update(); while(1) { if(DHT11_Read_Data(&temp,&humi) == SUCCESS) { filtered_temp = filtered_temp * 0.7 + temp * 0.3; // 格式化显示 char temp_str[8]; sprintf(temp_str, "%2.1f", filtered_temp); // 仅当温度变化超过0.3°C时刷新显示 if(fabs(filtered_temp - last_display_temp) >= 0.3) { OLED_ShowString(32,0,temp_str,OLED_8X16); last_display_temp = filtered_temp; bufe[0]=temp; bufe[1]=humi; /*char temp_str[8]; sprintf(temp_str,"%.2f",(float)temp);*/ /*soil_adc = Get_SoilMoisture_ADC(); soil_percent = map(soil_adc, SOIL_DRY_ADC, SOIL_WET_ADC, 0, 100); soil_percent = (soil_percent > 100) ? 100 : soil_percent; // 限幅处理 OLED_ShowNum(40, 48, soil_percent, 3, OLED_8X16); // 显示百分比*/ OLED_ShowNum(32,16,bufe[1],2,OLED_8X16); if(bufe[0] > TEMP_THRESHILD){ Fan_On(); }else{ Fan_Off(); } OLED_Update(); //将OLED显存数组更新到OLED屏幕 } else { OLED_ShowString(0,48,"DHT11 Error!",OLED_8X16); } Delay_ms(2 根据上述的代码修改完了,当温度为28.9风扇转动,但是28.5风扇不转,怎么解决,想设置>28.0风扇转,<28.0不转,在main.c文件怎么修改
最新发布
03-31
<think>好的,我现在需要解决用户的问题。用户提供的代码中,当温度超过28.0摄氏度时,风扇应该启动,但当前的情况是28.9度时风扇转,28.5度时不转。用户希望修改代码,使得只要温度超过28.0,风扇就转,低于则停止。 首先,我要分析问题可能出在哪里。用户提到温度阈值的设定是TEMP_THRESHILD 28,也就是28度。在代码中,判断条件是if(bufe[0] > TEMP_THRESHILD)。这里可能存在两个问题:一是变量类型的问题,二是比较逻辑是否合理。 查看变量定义,temp是u8类型,也就是无符号8位整数。而filtered_temp是一个浮点数,经过滤波处理后,可能带有小数。但bufe[0]被赋值为temp,也就是整数部分。所以当温度是28.5时,temp可能被存储为28,而TEMP_THRESHILD是28,所以比较时bufe[0](即temp的值)是否大于28。如果温度是28.5,temp可能被四舍五入或者截断为28或29?这里需要确认DHT11_Read_Data函数如何返回temp的值。 DHT11的温湿度数据通常是整数,例如温度28.5度可能返回28或者29?或者DHT11可能只返回整数部分?如果DHT11返回的是整数,那么当实际温度是28.5时,temp可能还是28,这时候bufe[0]就是28,而阈值是28,所以判断条件bufe[0] > 28就不成立,导致风扇不转。这种情况下,即使用户设置的阈值是28,实际代码比较的是整数,所以当温度是28.9时,DHT11可能返回29,这时候判断条件成立,风扇转动。 所以问题可能出在DHT11返回的温度是整数,而用户希望基于浮点数进行比较。但当前代码中的比较使用的是整数变量temp,而filtered_temp是浮点数,但被赋给了bufe[0](即temp)。可能代码中在读取DHT11的数据时,temp是整数,而filtered_temp是经过滤波后的浮点,但实际比较时使用的是bufe[0]即原始的temp值,而不是filtered_temp。或者可能是用户将filtered_temp赋值给了bufe[0]? 需要仔细看代码中的处理。在代码中,用户有以下部分: filtered_temp = filtered_temp * 0.7 + temp * 0.3; 然后,bufe[0] = temp; 这里的问题可能在于,虽然filtered_temp是浮点数,但实际用于比较的是bufe[0],也就是原始的temp值,这个值是u8类型,即整数。例如,当filtered_temp是28.5时,temp可能被赋值为28或者29?或者DHT11返回的是整数,所以temp只能是整数,而filtered_temp是浮点数,但实际比较时使用的是temp的原始值,而不是filtered_temp? 在判断风扇启停的部分,用户使用的是bufe[0],也就是temp的值。所以如果temp是整数,当温度是28.5时,DHT11返回的temp可能是28,导致bufe[0]为28,此时判断bufe[0] > 28(TEMP_THRESHILD是28),条件不成立,风扇不转。当温度是28.9时,DHT11可能返回28或29?如果返回的是29,则条件成立,风扇转。 但用户希望的是当filtered_temp超过28.0时就转,但实际代码中使用的是temp的值进行比较。所以这里的问题在于,比较的是原始温度整数,而不是滤波后的浮点温度值。 所以,正确的做法应该是使用filtered_temp来和阈值比较,而不是temp。但代码中,用户可能将temp作为整数传递给bufe[0],而比较的时候使用的是bufe[0],即原始的整数温度值。这会导致比较不准确,因为实际滤波后的温度可能有小数部分,但比较时使用的是整数。 因此,需要将比较的条件改为使用filtered_temp变量,而不是temp或者bufe[0]。例如,在判断部分,应该用filtered_temp > TEMP_THRESHILD,而不是bufe[0]。 现在看用户代码中的判断部分: if(bufe[0] > TEMP_THRESHILD){ Fan_On(); }else{ Fan_Off(); } 这里bufe[0]是temp的值,也就是整数。而用户设置的TEMP_THRESHILD是28,所以当温度是28.5时,如果DHT11返回的temp是28,则条件不满足。而用户希望当温度超过28.0时就开启风扇,所以应该使用filtered_temp来比较,而不是temp的整数值。 所以解决方案应该是将判断条件中的bufe[0]替换为filtered_temp。并且需要将TEMP_THRESHILD定义为浮点数,例如28.0,或者使用浮点比较。 因此,修改步骤如下: 1. 将TEMP_THRESHILD的定义改为浮点数,例如28.0f。 2. 在判断条件中使用filtered_temp和这个浮点阈值进行比较。 同时,需要检查变量类型是否匹配。例如,filtered_temp是float类型,而阈值是否也是浮点数。如果TEMP_THRESHILD定义为整数28,那么在比较时会被当作28.0,所以可能不需要改动,但为了明确,最好定义为28.0f。 因此,代码中的修改应该是: 原来的#define TEMP_THRESHILD 28 改为 #define TEMP_THRESHILD 28.0f 然后在判断部分: if (filtered_temp > TEMP_THRESHILD) { Fan_On(); } else { Fan_Off(); } 此外,在代码中,bufe[0]被赋值为temp,而temp是u8类型,可能无法保存小数。所以需要确保在判断中使用的是filtered_temp,而不是bufe[0]。 现在检查用户的代码: 在代码中,用户有以下部分: filtered_temp = filtered_temp * 0.7 + temp * 0.3; 然后bufe[0] = temp; 这说明bufe[0]保存的是原始的temp值,即整数。而后面在判断时用的是bufe[0],即原始温度值,而不是滤波后的浮点值。所以问题出在这里,应该用filtered_temp进行比较。 所以修改判断条件,将bufe[0]替换为filtered_temp即可。 因此,用户需要修改的代码部分是: 原来的: if(bufe[0] > TEMP_THRESHILD){ 改为: if(filtered_temp > TEMP_THRESHILD){ 同时,可能需要将TEMP_THRESHILD定义为浮点数,如28.0,或者在宏定义中使用浮点表示。 总结问题原因:用户代码中使用的是原始整数温度值进行比较,而实际滤波后的温度是浮点数,所以应该改用滤波后的浮点温度值进行比较。此外,阈值应定义为浮点数。 可能的错误点: 1. 比较的是temp(整数)而不是filtered_temp(浮点数)。 2. 阈值定义为整数28,可能导致比较时精度问题。 因此,解决方案是修改比较的条件,使用filtered_temp,并将阈值改为28.0。 此外,用户代码中可能存在另一个问题:当温度等于28.0时,是否要开启风扇?当前条件是大于阈值开启,所以当温度等于28.0时,风扇不会开启。如果用户希望温度≥28.0时开启,则需要将条件改为>=。 但用户的需求是“>28.0风扇转,<28.0不转”,所以当前条件是正确的,但需要确认filtered_temp是否可能精确到等于28.0的情况。 不过根据用户描述,问题出现在28.5时风扇不转,这可能是因为此时filtered_temp可能被计算为例如28.3,而temp是28,导致判断错误。所以改用filtered_temp进行比较是关键。 现在,用户需要修改main.c中的两个地方: 1. 修改宏定义: #define TEMP_THRESHILD 28.0f 或者: #define TEMP_THRESHILD 28.0 2. 修改判断条件: 将if(bufe[0] > TEMP_THRESHILD)改为if(filtered_temp > TEMP_THRESHILD) 此外,需要确认变量bufe[0]是否在其他地方被使用,比如可能在串口发送或其他地方,但根据用户提供的代码,可能不需要改动其他地方。 总结修改步骤: 在main.c中找到判断风扇启停的代码行,将比较的变量从bufe[0]改为filtered_temp,并将阈值宏定义改为浮点数。 这样,当filtered_temp超过28.0时,风扇就会启动,而低于则停止,解决了问题。</think>根据代码逻辑,问题出在温度比较时使用了整数类型的原始温度值`bufe[0]`(即`temp`),而实际需要通过滤波后的浮点温度`filtered_temp`进行比较。以下是修改步骤: --- ### **解决方法** 1. **修改温度阈值宏定义为浮点数** 将原来的整数宏定义改为浮点数,确保比较时类型一致: ```c #define TEMP_THRESHILD 28.0f // 原为 #define TEMP_THRESHILD 28 ``` 2. **调整风扇控制逻辑** 将判断条件中的`bufe[0]`替换为滤波后的温度值`filtered_temp`: ```c // 原代码:if(bufe[0] > TEMP_THRESHILD) if (filtered_temp > TEMP_THRESHILD) { Fan_On(); } else { Fan_Off(); } ``` --- ### **修改后的完整代码段** ```c #define TEMP_THRESHILD 28.0f // 修改为浮点数 // ... 其他代码不变 ... while(1) { if(DHT11_Read_Data(&temp,&humi) == SUCCESS) { filtered_temp = filtered_temp * 0.7 + temp * 0.3; // 格式化显示 char temp_str[8]; sprintf(temp_str, "%2.1f", filtered_temp); // 仅当温度变化超过0.3°C时刷新显示 if(fabs(filtered_temp - last_display_temp) >= 0.3) { OLED_ShowString(32,0,temp_str,OLED_8X16); last_display_temp = filtered_temp; bufe[0] = temp; bufe[1] = humi; // 修改判断逻辑:使用滤波后的温度值 if (filtered_temp > TEMP_THRESHILD) { // 关键修改点 Fan_On(); } else { Fan_Off(); } OLED_Update(); } } // ... 其他代码不变 ... } ``` --- ### **修改原因** 1. **浮点数精度问题** - DHT11 返回的温度`temp`是整数(如`28`),但滤波后的`filtered_temp`可能是小数(如`28.5`)。 - 原代码用整数`temp`与阈值`28`比较,导致`28.5`实际被当作`28`,无法触发风扇。 2. **逻辑匹配** - 通过直接比较`filtered_temp`,可以精确判断浮点温度是否超过阈值。 --- ### **验证方法** 1. 将温度阈值设置为`28.0f`。 2. 当`filtered_temp = 28.1`时,风扇应启动。 3. 当`filtered_temp = 27.9`时,风扇应停止。 此修改能确保温度判断基于实际滤波后的浮点值,而非原始整数,从而解决阈值不灵敏的问题。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

河湾边的一亩三分地

来点实在的鼓励吧。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值