打印
[STM32H5]

【NUCLEO-H563ZI测评】5.UART通讯+SPI驱动LCD12864+温湿度读取

[复制链接]
547|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
#申请原创# @21小跑堂  
5.UART通讯+SPI驱动LCD12864+温湿度读取
5.1UART通讯测试
UART在嵌入式领域应用的非常广泛,这块板子引出了一路串口接到了STLink的串口上,倒也省得再找USB转串口了,直接用这个测试一下串口功能

双击工程目录中的.ioc文件打开STM32CubeMX,找到USART3,可以看到默认的参数配置:波特率115200 数据位8 停止位1 无流控制和校验位

打开MDK,先写个按下按键通过串口发送数据的程序,代码示例

const char *uarttestdata = "NUCLEO-H563ZI 串口3测试\r\n";
void HAL_GPIO_EXTI_Rising_Callback(uint16_t GPIO_Pin)
{
    if(HAL_GPIO_ReadPin(USER_BUTTON_GPIO_Port,USER_BUTTON_Pin) == GPIO_PIN_SET)
    {
        HAL_UART_Transmit(&huart3,(uint8_t *)uarttestdata,strlen(uarttestdata),100);
    }
}
烧录后用串口调试助手测试

接下来修改一下,开启中断,用串口将接收到的数据原样返回,默认的这里是Enable要改成Disable,不然发送的数据和返回的不一致

在STM32CubeMX中打开串口中断

点击生成代码,打开MDK,同样在串口初始化后也要手动开启中断接收

示例代码

uint8_t uartrxbuffer[1] = {0};
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if(huart->Instance == USART3)
    {
        HAL_UART_Transmit(huart,uartrxbuffer,1,100);
        HAL_UART_Receive_IT(huart,uartrxbuffer,1);
    }
}
如果想用空闲中断可以这么写
#define UARTRXBUFFERLEN 50
uint8_t uartrxbuffer[UARTRXBUFFERLEN] = {0};
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
    if(huart->RxEventType == HAL_UART_RXEVENT_IDLE)
    {
        HAL_UART_Transmit(huart,uartrxbuffer,Size,100);
        HAL_UARTEx_ReceiveToIdle_IT(huart,uartrxbuffer,UARTRXBUFFERLEN);
    }
}
串口初始化最后的开启中断接收也要换成HAL_UARTEx_ReceiveToIdle_IT(&huart3,uartrxbuffer,UARTRXBUFFERLEN);
运行效果


5.2SPI驱动LCD12864
SPI是一种高速的全双工同步的通信总线,需要至少SCK MOSI MISO三根线实现数据双向传输,可以通过片选线来实现对不同设备的访问
手上有个12864的LCD屏,用SPI驱动的,尝试用这块板子点亮一下,驱动这个屏需要用到5个IO:SCK MOSI CS RST A0都是输出模式,打开STM32CubeMX找到SPI,数据是单向传输的因此SPI配置成仅发送就行了

看一下用到的GPIO,默认的SCK是PA5 MOSI是PD7

但是原理图上这组SPI的MOSI是PB5

手动改一下,点击PB5选择SPI1_MOSI就行了

剩下的CS用PD14 RST用PB12 A0用PC7,都设置为输出,代码示例

YUYY_HS12864G18B_DEV_t hs12864_dev;
void lcd12864_init()
{
    hs12864_dev.spix = &hspi1;
    hs12864_dev.a0.gpio = LCD_A0_GPIO_Port;
    hs12864_dev.a0.pin = LCD_A0_Pin;
    hs12864_dev.cs.gpio = LCD_CS_GPIO_Port;
    hs12864_dev.cs.pin = LCD_CS_Pin;
    hs12864_dev.rst.gpio = LCD_RST_GPIO_Port;
    hs12864_dev.rst.pin = LCD_RST_Pin;
    yuyy_hs12864g18b_init(&hs12864_dev);
    yuyy_hs12864g18b_clear_screen(&hs12864_dev);
    yuyy_hs12864g18b_display_string_8x16(&hs12864_dev,0,0,0,(uint8_t *)"NUCLEO-H563ZI");
    yuyy_hs12864g18b_display_string_8x16(&hs12864_dev,0,2,0,(uint8_t *)"SPI LCD Test");
    yuyy_hs12864g18b_display_string_8x16(&hs12864_dev,0,4,0,(uint8_t *)"Code by yuyy1989");
    yuyy_hs12864g18b_display_finish(&hs12864_dev);
}
显示效果

5.3读取DHT11温湿度
DHT11采用的是单总线通讯,即用一根数据线完成数据交换,MCU在通讯时需要切换IO的输入输出,对于这种情况可以使用GPIO的开漏输出来实现
开漏输出模式下GPIO可以强制拉低,但是需要拉高时需要借助外部的上拉电阻,而DHT11模块正好内置了10K的上拉电阻,这样作为输出时就能正常输出0或1,想要作为输入时只需要程序内输出1这样DHT11就能输出0或1,通过读取GPIO的实际电平就完成了数据的输入
打开STM32CubeMX,选择PG9作为DHT11的数据线,配置为开漏输出

按照手册的通讯规则写好获取温湿度的代码,通过LCD屏来显示温湿度

YUYY_DHT11_DEV_t dht11_dev;
void dht11_init()
{
    dht11_dev.dat.gpio = DHT11_DAT_GPIO_Port;
    dht11_dev.dat.pin = DHT11_DAT_Pin;
}
void usercode_loop(void)
{
    float HumF,TemF;
    char out[20];
    uint8_t err=0,outlen;
    yuyy_delay_ms(2000);
    err = yuyy_dht11_readHT(&dht11_dev,&TemF,&HumF);
    outlen = sprintf(out,"%d %.1f%% %.1f",err,HumF,TemF);
    yuyy_hs12864g18b_display_string_8x16(&hs12864_dev,0,4,0,(uint8_t *)out);
    yuyy_hs12864g18b_display_graphic_16x16(&hs12864_dev,0,4,8*outlen,(uint8_t *)test16x16temp);
    yuyy_hs12864g18b_display_string_8x16(&hs12864_dev,0,4,8*(outlen+2),(uint8_t *)"      ");
    yuyy_hs12864g18b_display_finish(&hs12864_dev);
}
编译烧录查看运行效果

5.4I2C读取DHTC12温湿度
和上面的单总线不同,I2C属于两线式串行总线,使用一个时钟线和一个数据线,属于一主多从的总线结构,总线上的每个设备都有一个特定的设备地址,以区分同一I2C总线上的其他设备。这里用软件I2C来通讯,选用PF0为SDA PF1为SCL,在STM32CubeMX中将这两个IO设置为开漏输出,演示代码

YUYY_IIC_DEV_t iic_dev;
YUYY_SOFT_IIC_DEV_t siic_dev;
YUYY_DHTC12_DEV_t dhtc12_dev;
void softiic_init()
{
    siic_dev.scl.gpio = SI2C_SCL_GPIO_Port;
    siic_dev.scl.pin = SI2C_SCL_Pin;
    siic_dev.sda.gpio = SI2C_SDA_GPIO_Port;
    siic_dev.sda.pin = SI2C_SDA_Pin;
    yuyy_soft_iic_init(&siic_dev);
        iic_dev.iictype = YUYY_IIC_TYPE_SOFT;
    iic_dev.siicx = &siic_dev;
}
void dhtc12_init()
{
    dhtc12_dev.iicx = &iic_dev;
    yuyy_dhtc12_init(&dhtc12_dev);
}
void usercode_loop(void)
{
    float HumF,TemF;
    char out[20];
    uint8_t err=0,outlen;
    yuyy_delay_ms(2000);
    err = yuyy_dhtc12_readHT(&dhtc12_dev,&TemF,&HumF);
    yuyy_hs12864g18b_display_string_8x16(&hs12864_dev,0,4,0,(uint8_t *)out);
    yuyy_hs12864g18b_display_graphic_16x16(&hs12864_dev,0,4,8*outlen,(uint8_t *)test16x16temp);
    yuyy_hs12864g18b_display_string_8x16(&hs12864_dev,0,4,8*(outlen+2),(uint8_t *)"      ");
    yuyy_hs12864g18b_display_finish(&hs12864_dev);
}
运行效果


使用特权

评论回复
沙发
huangcunxiake| | 2023-8-17 17:06 | 只看该作者
这个帖子有内容,刚才看的另外两个太菜了。给楼主点赞。

使用特权

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

本版积分规则

149

主题

708

帖子

7

粉丝