返回列表 发新帖我要提问本帖赏金: 20.00元(功能说明)

[活动] 【极海APM32F407IG Tiny Board开发板测评】5.UART通讯+SPI驱动LCD12864+I2C读取DHTC12温湿度

[复制链接]
1995|10
 楼主| yuyy1989 发表于 2023-7-10 13:42 | 显示全部楼层 |阅读模式
本帖最后由 yuyy1989 于 2023-7-11 17:40 编辑

#申请原创# @21小跑堂  
5.UART通讯+SPI驱动LCD12864+I2C读取DHTC12温湿度
5.1 UART串口通讯
UART在嵌入式领域应用的非常广泛,APM32F407拥有4个USART和2个UART,板子上引出的串口时USART1 TX:PA9 RX:PA10
QQ截图20230710133342.png
简单做一个将接收到的数据原样返回的程序,代码示例

  1. #include "Board_APM32F407_TINY.h"
  2. #include "bsp_delay.h"
  3. #include "apm32f4xx_tmr.h"

  4. #define UART_BUFFER_LEN 30
  5. uint8_t uart_buffer[UART_BUFFER_LEN] = {0};
  6. uint8_t uart_rxindex = 0;
  7. uint8_t uart_rxlen = 0;
  8. uint8_t uart_txindex = 0;
  9. uint8_t uart_txlen = 0;

  10. void uart_init()
  11. {
  12.     USART_Config_T usartConfigStruct;

  13.     usartConfigStruct.baudRate = 115200;
  14.     usartConfigStruct.hardwareFlow = USART_HARDWARE_FLOW_NONE;
  15.     usartConfigStruct.mode = USART_MODE_TX_RX;
  16.     usartConfigStruct.parity = USART_PARITY_NONE;
  17.     usartConfigStruct.stopBits = USART_STOP_BIT_1;
  18.     usartConfigStruct.wordLength = USART_WORD_LEN_8B;
  19.     APM_TINY_COMInit(COM1, &usartConfigStruct);
  20.    
  21.     USART_EnableInterrupt(TINY_COM1, USART_INT_RXBNE);
  22.     USART_EnableInterrupt(TINY_COM1, USART_INT_IDLE);
  23.     USART_ClearStatusFlag(TINY_COM1, USART_FLAG_RXBNE);
  24.     NVIC_EnableIRQRequest(TINY_COM1_IRQn,0,0);
  25. }

  26. void readrxtotxbuffer()
  27. {
  28.     uart_txlen += uart_rxlen;
  29.     uart_rxlen = 0;
  30.     USART_EnableInterrupt(TINY_COM1, USART_INT_TXBE);
  31. }

  32. int main(void)
  33. {
  34.     APM_DelayInit();
  35.     uart_init();
  36.     while (1)
  37.     {
  38.     }
  39. }

  40. void SysTick_Handler(void)
  41. {
  42.     APM_DelayTickDec();
  43. }

  44. void USART1_IRQHandler(void)
  45. {
  46.     if(USART_ReadStatusFlag(TINY_COM1, USART_FLAG_RXBNE) == SET){
  47.         uart_buffer[uart_rxindex++] = (uint8_t)USART_RxData(TINY_COM1);
  48.         if(uart_rxindex == UART_BUFFER_LEN)
  49.             uart_rxindex = 0;
  50.         uart_rxlen++;
  51.     }
  52.     if(USART_ReadStatusFlag(TINY_COM1, USART_FLAG_IDLE) == SET|| uart_rxlen == 10) {
  53.         USART_ClearStatusFlag(TINY_COM1, USART_FLAG_IDLE);
  54.         readrxtotxbuffer();
  55.     }
  56.     if(USART_ReadStatusFlag(TINY_COM1, USART_FLAG_TXBE) == SET){
  57.         if(uart_txlen > 0)
  58.         {
  59.             USART_TxData(TINY_COM1,uart_buffer[uart_txindex++]);
  60.             if(uart_txindex == UART_BUFFER_LEN)
  61.                 uart_txindex = 0;
  62.             uart_txlen--;
  63.         }
  64.         else
  65.         {
  66.             USART_DisableInterrupt(TINY_COM1, USART_INT_TXBE);
  67.         }
  68.     }
  69. }
编译烧录查看效果
板子上的Geehy LINK没有串口功能,还要额外找个USB转串口工具测试,按顺序连接好串口接线
微信图片_20230710133559.jpg
打开串口工具,发送任意字符串
QQ截图20230708195126.png
5.2 SPI驱动12864LCD
SPI是一种高速的全双工同步的通信总线,需要至少SCK MOSI MISO三根线实现数据双向传输,可以通过片选线来实现对不同设备的访问
APM32F407拥有3个SPI,手上有个12864的LCD屏,用SPI驱动的,尝试用这块板子点亮一下
通讯需要用到5个IO:SCK MOSI CS RST A0都是输出模式,SCK用PA5 MOSI用PA7,其它的就随意了
QQ截图20230708205123.png
数据是单向传输的因此SPI配置成仅发送就行了,代码示例

  1. #include "Board_APM32F407_TINY.h"
  2. #include "bsp_delay.h"
  3. #include "apm32f4xx_tmr.h"
  4. #include "apm32f4xx_spi.h"
  5. #include "yuyy_project_config.h"
  6. #include "yuyy_hs12864g18b.h"

  7. Yuyy_Hs12864g18b_Gpio_Config_t hs12864g18b_gpio_config;
  8. void hs12864g18b_init()
  9. {
  10.     GPIO_Config_T GPIO_InitStructure;
  11.     SPI_Config_T  SPI1_InitStructure;
  12.    
  13.     RCM_EnableAHB1PeriphClock (RCM_AHB1_PERIPH_GPIOA);
  14.     RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SPI1);
  15.     RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SYSCFG);
  16.    
  17.     hs12864g18b_gpio_config.cs.gpio = GPIOA;
  18.     hs12864g18b_gpio_config.cs.pin = GPIO_PIN_3;
  19.     hs12864g18b_gpio_config.rst.gpio = GPIOA;
  20.     hs12864g18b_gpio_config.rst.pin = GPIO_PIN_4;
  21.     hs12864g18b_gpio_config.a0.gpio = GPIOA;
  22.     hs12864g18b_gpio_config.a0.pin = GPIO_PIN_6;
  23.     hs12864g18b_gpio_config.sck.gpio = GPIOA;
  24.     hs12864g18b_gpio_config.sck.pin = GPIO_PIN_5;
  25.     hs12864g18b_gpio_config.mo.gpio = GPIOA;
  26.     hs12864g18b_gpio_config.mo.pin = GPIO_PIN_7;
  27.    
  28.     GPIO_ConfigStructInit(&GPIO_InitStructure);
  29.     GPIO_InitStructure.pin = GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_6;
  30.     GPIO_InitStructure.speed = GPIO_SPEED_100MHz;
  31.     GPIO_InitStructure.mode = GPIO_MODE_OUT;
  32.     GPIO_InitStructure.otype = GPIO_OTYPE_PP;
  33.     GPIO_InitStructure.pupd = GPIO_PUPD_NOPULL;
  34.     GPIO_Config(GPIOA, &GPIO_InitStructure);
  35.    
  36.     #if(YUYY_HS12864G18B_USE_SOFT_SPI)
  37.     GPIO_InitStructure.pin = GPIO_PIN_5 | GPIO_PIN_7;
  38.     GPIO_InitStructure.mode = GPIO_MODE_OUT;
  39.     GPIO_Config(GPIOA, &GPIO_InitStructure);
  40.     yuyy_hs12864g18b_set_spigpio(NULL,&hs12864g18b_gpio_config);
  41.     #else
  42.     GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_5, GPIO_AF_SPI1);
  43.     GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_7, GPIO_AF_SPI1);
  44.     GPIO_InitStructure.pin = GPIO_PIN_5 | GPIO_PIN_7;
  45.     GPIO_InitStructure.mode = GPIO_MODE_AF;
  46.     GPIO_Config(GPIOA, &GPIO_InitStructure);
  47.    
  48.     SPI_ConfigStructInit(&SPI1_InitStructure);
  49.     SPI1_InitStructure.direction = SPI_DIRECTION_1LINE_TX; //只需要发送
  50.     SPI1_InitStructure.mode = SPI_MODE_MASTER;
  51.     SPI1_InitStructure.length = SPI_DATA_LENGTH_8B;        //数据长度8bit
  52.     SPI1_InitStructure.polarity = SPI_CLKPOL_HIGH;         //空闲时SCK高电平
  53.     SPI1_InitStructure.phase = SPI_CLKPHA_2EDGE;           //第二个边沿采样
  54.     SPI1_InitStructure.nss = SPI_NSS_SOFT;                 //软件控制片选
  55.     SPI1_InitStructure.baudrateDiv = SPI_BAUDRATE_DIV_8;   //时钟分频系数
  56.     SPI1_InitStructure.firstBit = SPI_FIRSTBIT_MSB;
  57.     SPI_Config(SPI1, &SPI1_InitStructure);
  58.     SPI_DisableCRC(SPI1);
  59.     SPI_Enable(SPI1);
  60.    
  61.     yuyy_hs12864g18b_set_spigpio(SPI1,&hs12864g18b_gpio_config);
  62.     #endif
  63.     yuyy_hs12864g18b_init();
  64.     yuyy_hs12864g18b_clear_screen();
  65. }

  66. void yuyy_hard_spi_writebyte(YUYY_SPI_TYPE spix,uint8_t dat)
  67. {
  68.     while (SPI_I2S_ReadStatusFlag(spix, SPI_FLAG_TXBE) == RESET);
  69.     SPI_I2S_TxData(spix, dat);
  70. }

  71. int main(void)
  72. {
  73.     APM_DelayInit();
  74.     hs12864g18b_init();
  75.     yuyy_hs12864g18b_display_string_8x16(0,0,0,(uint8_t *)"APM32F407IG TEST");
  76.     yuyy_hs12864g18b_display_string_8x16(0,2,0,(uint8_t *)"Tiny Board v1.0");
  77.     yuyy_hs12864g18b_display_string_8x16(0,4,0,(uint8_t *)"Code by yuyy1989");
  78.     while (1)
  79.     {
  80.     }
  81. }

  82. void SysTick_Handler(void)
  83. {
  84.     APM_DelayTickDec();
  85. }
编译烧录查看效果
微信图片_20230710134023.jpg
5.3 I2C读取DHTC12温湿度
I2C属于两线式串行总线,属于一主多从的总线结构,总线上的每个设备都有一个特定的设备地址,以区分同一I2C总线上的其他设备。
APM32F407拥有3个I2C,很多传感器都是用I2C进行通讯的,接下来尝试用I2C读取DHTC12温湿度,选用PF0 PF1
QQ截图20230710094514.png
尝试用硬件I2C,结果在调用I2C_EnableGenerateStart后无论等多久I2C_ReadEventStatus(iicx, I2C_EVENT_MASTER_MODE_SELECT)返回的都是0
想参考bsp_i2c.c的驱动代码,结果用的是软件I2C,索性直接用软件I2C了,通讯代码可以直接参考bsp_i2c.c
运行效果
微信图片_20230711174005.jpg

打赏榜单

Gfan 打赏了 20.00 元 2023-08-17
理由:APM32F407IG Tiny Board精选测评

评论

赞,学习一下  发表于 2023-7-10 17:41
caizhiwei 发表于 2023-7-11 11:20 | 显示全部楼层
tpgf 发表于 2023-8-3 16:14 | 显示全部楼层
好像是同时使用了这几种通讯方式是吗
qcliu 发表于 2023-8-3 16:44 | 显示全部楼层
同时进行的话 需要跑系统来实现吗
drer 发表于 2023-8-3 17:03 | 显示全部楼层
qcliu 发表于 2023-8-3 16:44
同时进行的话 需要跑系统来实现吗

跑不跑系统的 都行 看个人习惯吧
coshi 发表于 2023-8-3 17:31 | 显示全部楼层
感觉温度的精度如何 需要校正吗
kxsi 发表于 2023-8-4 10:15 | 显示全部楼层
这种读取温湿度的协议 是一问一答还是不停的回答啊
 楼主| yuyy1989 发表于 2023-8-4 10:19 | 显示全部楼层
kxsi 发表于 2023-8-4 10:15
这种读取温湿度的协议 是一问一答还是不停的回答啊

一问一答
wiba 发表于 2023-8-4 10:46 | 显示全部楼层
这种变化不剧烈的数据 对通讯的速度要求的就非常低了吧
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:同飞软件研发工程师
简介:制冷系统单片机软件开发,使用PID控制温度

168

主题

826

帖子

10

粉丝
快速回复 在线客服 返回列表 返回顶部