打印
[AT32L021]

【AT-START-L021测评】+ SPI驱动ST7789 2.0寸屏幕显示温湿度

[复制链接]
36|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 xiaoqi976633690 于 2024-11-29 17:04 编辑

#申请原创#
一、项目描述
1.项目介绍
项目基于AT-START-L021 V1.0  开发板驱动SPI 屏幕显示温湿度信息和倒计时器。
2.设计思路
SPI驱动采用硬件SPI和软件模拟SPI(可选)默认硬件SPI,I2C采用软件模拟时序。
3.硬件
2.0寸ST7789屏幕+AHT20温湿度传感器
二、软件代码说明
1.SPI初始化
注意事项
a.注意SPI的复用mux
 gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE5, GPIO_MUX_0);
  gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE6, GPIO_MUX_0);
  gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE7, GPIO_MUX_0);
b.注意SCK引脚内部下拉配置
  gpio_initstructure.gpio_pull           = GPIO_PULL_DOWN;
c.注意SPI模式的配置关键点:  
1.spi_init_struct.mclk_freq_division = SPI_MCLK_DIV_2;//分频系数影响spi速率
2.spi_init_struct.first_bit_transmission = SPI_FIRST_BIT_MSB;//高位在前
3.  spi_init_struct.clock_polarity = SPI_CLOCK_POLARITY_LOW;//clk空闲为低  
  spi_init_struct.clock_phase = SPI_CLOCK_PHASE_1EDGE;//第一个边沿采样

void SPI1_config(void)
{
        
        spi_init_type spi_init_struct;
        gpio_init_type gpio_initstructure;
        
  crm_periph_clock_enable(CRM_SPI1_PERIPH_CLOCK, TRUE);
  crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
  crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);

  gpio_default_para_init(&gpio_initstructure);
        
        #ifdef SOFT_SPI
        //SPI1_SCK
  gpio_initstructure.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;
  gpio_initstructure.gpio_pull           = GPIO_PULL_UP;
  gpio_initstructure.gpio_mode           = GPIO_MODE_OUTPUT;
  gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_initstructure.gpio_pins = GPIO_PINS_5;
  gpio_init(GPIOA, &gpio_initstructure);
        //SPI1_MOSI
  gpio_initstructure.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;
  gpio_initstructure.gpio_pull           = GPIO_PULL_UP;
  gpio_initstructure.gpio_mode           = GPIO_MODE_OUTPUT;
  gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_initstructure.gpio_pins = GPIO_PINS_7;
  gpio_init(GPIOA, &gpio_initstructure);
        #else
        gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE5, GPIO_MUX_0);
  gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE6, GPIO_MUX_0);
  gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE7, GPIO_MUX_0);
                //SPI1_SCK
  gpio_initstructure.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;
  gpio_initstructure.gpio_pull           = GPIO_PULL_DOWN;
  gpio_initstructure.gpio_mode           = GPIO_MODE_MUX;
  gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_initstructure.gpio_pins = GPIO_PINS_5;
  gpio_init(GPIOA, &gpio_initstructure);
        //SPI1_MISO
  gpio_initstructure.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;
  gpio_initstructure.gpio_pull           = GPIO_PULL_UP;
  gpio_initstructure.gpio_mode           = GPIO_MODE_MUX;
  gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_initstructure.gpio_pins = GPIO_PINS_6;
  gpio_init(GPIOA, &gpio_initstructure);
        //SPI1_MOSI
  gpio_initstructure.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;
  gpio_initstructure.gpio_pull           = GPIO_PULL_UP;
  gpio_initstructure.gpio_mode           = GPIO_MODE_MUX;
  gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_initstructure.gpio_pins = GPIO_PINS_7;
  gpio_init(GPIOA, &gpio_initstructure);         
#endif
                //CS
  gpio_initstructure.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;
  gpio_initstructure.gpio_pull           = GPIO_PULL_UP;
  gpio_initstructure.gpio_mode           = GPIO_MODE_OUTPUT;
  gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_initstructure.gpio_pins = GPIO_PINS_0;
  gpio_init(GPIOB, &gpio_initstructure);        
                //DC
  gpio_initstructure.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;
  gpio_initstructure.gpio_pull           = GPIO_PULL_UP;
  gpio_initstructure.gpio_mode           = GPIO_MODE_OUTPUT;
  gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_initstructure.gpio_pins = GPIO_PINS_1;
  gpio_init(GPIOB, &gpio_initstructure);        
                //RESET
  gpio_initstructure.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;
  gpio_initstructure.gpio_pull           = GPIO_PULL_UP;
  gpio_initstructure.gpio_mode           = GPIO_MODE_OUTPUT;
  gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_initstructure.gpio_pins = GPIO_PINS_2;
  gpio_init(GPIOB, &gpio_initstructure);        
        //BLK
  gpio_initstructure.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;
  gpio_initstructure.gpio_pull           = GPIO_PULL_UP;
  gpio_initstructure.gpio_mode           = GPIO_MODE_OUTPUT;
  gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_initstructure.gpio_pins = GPIO_PINS_10;
  gpio_init(GPIOB, &gpio_initstructure);        
        
//  LCD_SCLK_Clr();
//        LCD_MOSI_Clr();

        
  spi_default_para_init(&spi_init_struct);
  spi_init_struct.transmission_mode = SPI_TRANSMIT_FULL_DUPLEX;
  spi_init_struct.master_slave_mode = SPI_MODE_MASTER;
  spi_init_struct.mclk_freq_division = SPI_MCLK_DIV_2;
  spi_init_struct.first_bit_transmission = SPI_FIRST_BIT_MSB;
  spi_init_struct.frame_bit_num = SPI_FRAME_8BIT;
  spi_init_struct.clock_polarity = SPI_CLOCK_POLARITY_LOW;
  spi_init_struct.clock_phase = SPI_CLOCK_PHASE_1EDGE;
  spi_init_struct.cs_mode_selection = SPI_CS_SOFTWARE_MODE;
  spi_init(SPI1, &spi_init_struct);
        
  spi_enable(SPI1, TRUE);
        LCD_DC_Set() ;
        LCD_RES_Set();
        LCD_CS_Set() ;
        LCD_BLK_Set();
}
2.LCD读写函数和初始化


/******************************************************************************
      函数说明:LCD串行数据写入函数
      入口数据:dat  要写入的串行数据
      返回值:  无
******************************************************************************/

uint8_t spi_writebyte(uint8_t index,uint8_t TxData)
{
    uint8_t re;
    while(spi_i2s_flag_get(SPI1, SPI_I2S_TDBE_FLAG) == RESET);
    spi_i2s_data_transmit(SPI1, TxData);
    while(spi_i2s_flag_get(SPI1, SPI_I2S_RDBF_FLAG) == RESET);
    re = spi_i2s_data_receive(SPI1);
    return re;
}
void LCD_Writ_Bus(u8 dat) 
{        

#ifdef SOFT_SPI               
                u8 i;
        LCD_CS_Clr();
        for(i=0;i<8;i++)
        {                          
                LCD_SCLK_Clr();
                if(dat&0x80)
                {
                   LCD_MOSI_Set();
                }
                else
                {
                   LCD_MOSI_Clr();
                }
                LCD_SCLK_Set();
                dat<<=1;
        }        
  LCD_CS_Set();        
#else

        LCD_CS_Clr();
        spi_writebyte(0,dat);
  LCD_CS_Set();        

#endif
}
至此SPI和屏幕驱动已基本完成。

3.软件i2c和AHT20驱动代码
a.软件I2C比较简单这里参考的是普中科技的代码,就不贴出来了。增加了个I2C 总线器件查找函数
void scan_iic(void)
{
        u8 i=0,ack=1;
        printf("iic scaner\n");
        for(i=0;i<127;i=i+2)
        {
                IIC_Start();
                IIC_Send_Byte(i);
                ack=IIC_Wait_Ack();
                if(ack==0) printf("0x%x  ",i>>1);
                IIC_Stop();
        }
        printf("\n");
}
b.AHT20 温度读取函数
void read_AHT20(void)
{
        uint8_t   i;
        
        for(i=0; i<6; i++)
        {
                readByte[i]=0;
        }
        IIC_Start();//I2C启动

        IIC_Send_Byte(0x71);//I2C写数据
        ack_status = IIC_Wait_Ack();//收到的应答信息

        readByte[0]= IIC_Read_Byte(1);//I2C读取数据

        readByte[1]= IIC_Read_Byte(1);

        readByte[2]= IIC_Read_Byte(1);

        readByte[3]= IIC_Read_Byte(1);

        readByte[4]= IIC_Read_Byte(1);

        readByte[5]= IIC_Read_Byte(0);

        IIC_Stop();//I2C停止函数
        //判断读取到的第一个字节是不是0x08,0x08是该芯片读取流程中规定的,如果读取过程没有问题,就对读到的数据进行相应的处理
        if( (readByte[0] & 0x68) == 0x08 )
        {
                H1 = readByte[1];
                H1 = (H1<<8) | readByte[2];
                H1 = (H1<<8) | readByte[3];
                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("读取失败!!!");

        }
        printf("\r\n");
        //根据AHT20芯片中,温度和湿度的计算公式,得到最终的结果,通过串口显示
        printf("温度:%d%d.%d",T1/100,(T1/10)%10,T1%10);
        printf("湿度:%d%d.%d",H1/100,(H1/10)%10,H1%10);
        
        if(T1<=180)
        {
        LCD_ShowString(10,0,"T:",DARKBLUE,WHITE,32,0);
  LCD_ShowFloatNum1(44,0,(float)T1/10,4,DARKBLUE,WHITE,32);
        
        LCD_ShowString(150+50,0,"H:",DARKBLUE,WHITE,32,0);        
        LCD_ShowFloatNum1(184+50,0,(float)H1/10,4,DARKBLUE,WHITE,32);
        }
        else if(T1>180&&T1<270)
        {
                LCD_ShowString(10,0,"T:",BRED,WHITE,32,0);
                LCD_ShowFloatNum1(44,0,(float)T1/10,4,BRED,WHITE,32);
                LCD_ShowString(150+50,0,"H:",BRED,WHITE,32,0);        
          LCD_ShowFloatNum1(184+50,0,(float)H1/10,4,BRED,WHITE,32);
               
        }

        printf("\r\n");
        
}
c.AHT20 子函数
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);
        
}


void  reset_AHT20(void)
{

        IIC_Start();

        IIC_Send_Byte(0x70);
        ack_status = IIC_Wait_Ack();
//        if(ack_status) printf("1");
//        else printf("1-n-");
        IIC_Send_Byte(0xBA);
        ack_status = IIC_Wait_Ack();
//                if(ack_status) printf("2");
//        else printf("2-n-");
        IIC_Stop();

}



void  init_AHT20(void)
{
        IIC_Start();

        IIC_Send_Byte(0x70);
        ack_status = IIC_Wait_Ack();
//        if(ack_status) printf("3");
//        else printf("3-n-");        
        IIC_Send_Byte(0xE1);
        ack_status = IIC_Wait_Ack();
//        if(ack_status) printf("4");
//        else printf("4-n-");
        IIC_Send_Byte(0x08);
        ack_status = IIC_Wait_Ack();
//        if(ack_status) printf("5");
//        else printf("5-n-");
        IIC_Send_Byte(0x00);
        ack_status = IIC_Wait_Ack();
//        if(ack_status) printf("6");
//        else printf("6-n-");
        IIC_Stop();
}



void  startMeasure_AHT20(void)
{
        //------------
        IIC_Start();

        IIC_Send_Byte(0x70);
        ack_status = IIC_Wait_Ack();
//        if(ack_status) printf("7");
//        else printf("7-n-");
        IIC_Send_Byte(0xAC);
        ack_status = IIC_Wait_Ack();
//        if(ack_status) printf("8");
//        else printf("8-n-");
        IIC_Send_Byte(0x33);
        ack_status = IIC_Wait_Ack();
//        if(ack_status) printf("9");
//        else printf("9-n-");
        IIC_Send_Byte(0x00);
        ack_status = IIC_Wait_Ack();
//        if(ack_status) printf("10");
//        else printf("10-n-");
        IIC_Stop();
}

4.main函数
int main(void)
{
//        float t=0.01;
        u8 m=30,s=59;
  system_clock_config();
  at32_board_init();
  uart_print_init(115200);
        IIC_Init();
        SPI1_config();
        LCD_Init();
       
        LCD_Fill(0,0,LCD_H,LCD_W,WHITE);
//        LCD_Show_MY_Char(10+65+65,45,10,my_color,WHITE,110,0);
        scan_iic();
       
  while(1)
  {               
               
                s--;
                if(m<=0)
                {
                        m=30;
                }
                if(s<=0)
                {
                        s=60;
                        m--;
                }

                LCD_Show_MY_Char(10,50,m/10%10,my_color,WHITE,110,0);
                LCD_Show_MY_Char(10+65,50,m%10,my_color,WHITE,110,0);
                                       
                LCD_Fill(148,85,168,105,my_color);
                LCD_Fill(148,85+30,168,85+30+20,my_color);

                LCD_Show_MY_Char(10+65+60+45,50,s/10%10,my_color,WHITE,110,0);       
                LCD_Show_MY_Char(10+65+60+60+50,50,s%10,my_color,WHITE,110,0);
               
                LCD_ShowPicture(55,170,202,50,gImage_AT);
                at32_led_toggle(LED4);
        ///        printf("%d\n",Read1307(0x00));
                printf("UUID3=0x%x\n",UUID3);
                delay_ms(500);
                scan_iic();
                read_AHT20_once();
               
  }
}

三、演示效果






使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

35

主题

189

帖子

2

粉丝