本帖最后由 xld0932 于 2023-2-28 11:14 编辑
#申请原创# @21小跑堂
NBK-EBS003 IoT功能扩展板是新定义推出的基于NBK-RD8x3x核心底板上的扩展硬件,具有丰富的功能:
1.四个常规LED灯
2.三色RGB灯
3.触控按键、触控滑条
4.OLED显示模块
5.ESP-01 Wi-Fi模块
在之前的分享帖中我们已经介绍了LED灯、RGB灯的控制方式,对于NBK-EBS003 IoT功能扩展板亦是相同的控制原理,需要注意的是,如果是将NBK-ES003 IoT扩展板直接插在NBK-RD8x3x核心底板上,需要将核心底板上的J10跳帽移动一设置选项,这样才可以使用三色RGB灯正常显示哦;
本篇要主要来分享一下使用RD8T36系列芯片的USCI0接口的TWI工作模式完成对OLED的显示驱动,UART0接口完成与ESP-01 Wi-Fi模块的通讯,最后结合这两个功能完成通过ESP-01 Wi-Fi模块连接Wi-Fi后,与知心天气服务器进行连接,获取当地的实时温度,显示在OLED上……
当然在完成上述功能的前提下,我们还需要准备一下软硬件相关的资料:
1、RD8T36P48J芯片数据手册
2、易码魔盒EasyCodeCube_RDSV3.2.5_20230105
3、新定义NBK-RD8x3x应用资料
上面3个都可以在新定义官网的下载中心进行下载:https://www.rdsmcu.com/
4、NBK-EBS003 IoT扩展板原理图:
NBK-EBS003原理图.pdf
(135.27 KB, 下载次数: 10)
除了软件资料外,我们硬件平台也是不可缺少的:
1、NBK-RD8x3x核心底板
2、NBK-EBS003 IoT扩展板
3、RD LINK PRO
因为在NBK-RD8x3x核心底板上已经带有ISP下载功能模块,所以RD LINK PRO是可选择工具;ISP仅可以下载程序到MCU运行,通过实际的运行结果验证功能是否正常;而RD LINK PRO除了具有下载程序的功能之外,还带有脱机烧录、在线调试、仿真等等丰富的功能……各位小伙伴可以根据需要自行选择……
1.TWI底层驱动程序(中断方式 + 超时处理)
在TWM产生START信号、发送数据时,操作成功/完成后都会产生TWIF中断(中断打开的情况下),我们通过这个中断来判断操作是否完成,再结合TIMEOUT超时处理,这样可以保证程序不会因为通讯断开而导致程序卡死的现象,保证了程序的可靠性……
2.OLED驱动、配置及显示
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void OLED_Set_Pos(uint8_t x, uint8_t y)
- {
- OLED_TWI_WriteByte(0x78, 0x00, 0xB0 + y);
- OLED_TWI_WriteByte(0x78, 0x00, ((x & 0xF0) >> 4) | 0x10);
- OLED_TWI_WriteByte(0x78, 0x00, ((x & 0x0F) >> 0) | 0x00);
- }
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void OLED_Clear(void)
- {
- uint8_t i = 0, j = 0;
- for (i = 0; i < 8; i++)
- {
- OLED_TWI_WriteByte(0x78, 0x00, 0xb0 + i);
- OLED_TWI_WriteByte(0x78, 0x00, 0x00);
- OLED_TWI_WriteByte(0x78, 0x00, 0x10);
- for (j = 0; j < 128; j++)
- {
- OLED_TWI_WriteByte(0x78, 0x40, 0x00);
- }
- }
- }
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void OLED_PartClear(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1)
- {
- uint8_t i = 0, j = 0;
- for (i = x0; i < x1; i++)
- {
- for (j = y0; j < y1; j++)
- {
- OLED_TWI_WriteByte(0x78, 0x00, 0xB0 + i);
- OLED_TWI_WriteByte(0x78, 0x00, ((j & 0xF0) >> 4) | 0x10);
- OLED_TWI_WriteByte(0x78, 0x00, ((j & 0x0F) >> 0) | 0x00);
- OLED_TWI_WriteByte(0x78, 0x40, 0);
- }
- }
- }
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void OLED_ShowChar(uint8_t x, uint8_t y, char ch, uint8_t CharSize)
- {
- uint8_t i = 0;
- ch -= 0x20;
- if (x > (128 - 1))
- {
- x = 0;
- y = y + 2;
- }
- if (CharSize == 16)
- {
- OLED_Set_Pos(x, y);
- for (i = 0; i < 8; i++)
- {
- OLED_TWI_WriteByte(0x78, 0x40, F8x16[ch * 16 + i]);
- }
- OLED_Set_Pos(x, y + 1);
- for (i = 0; i < 8; i++)
- {
- OLED_TWI_WriteByte(0x78, 0x40, F8x16[ch * 16 + i + 8]);
- }
- }
- else
- {
- OLED_Set_Pos(x, y);
- for (i = 0; i < 6; i++)
- {
- OLED_TWI_WriteByte(0x78, 0x40, F6x8[ch][i]);
- }
- }
- }
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void OLED_ShowString(uint8_t x, uint8_t y, char *str, uint8_t CharSize)
- {
- unsigned char j = 0;
- while (*str != '\0')
- {
- OLED_ShowChar(x, y, *str, CharSize);
- x += 8;
- if (x > 120)
- {
- x = 0;
- y += 2;
- }
- str++;
- }
- }
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void OLED_Init(void)
- {
- TWI0_InterruptFlag = 0;
- GPIO_Init(GPIO0, GPIO_PIN_5, GPIO_MODE_IN_PU);
- USCI0_TWI_GeneralCallCmd(ENABLE);
- USCI0_TWI_AcknowledgeConfig(ENABLE);
- USCI0_ITConfig(ENABLE, LOW);
- USCI0_TWI_MasterCommunicationRate(USCI0_TWI_32);
- USCI0_TWI_Cmd(ENABLE);
- }
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void OLED_Configure(void)
- {
- OLED_TWI_WriteByte(0x78, 0x00, 0xAE);
- OLED_TWI_WriteByte(0x78, 0x00, 0x00);
- OLED_TWI_WriteByte(0x78, 0x00, 0x10);
- OLED_TWI_WriteByte(0x78, 0x00, 0x40);
- OLED_TWI_WriteByte(0x78, 0x00, 0xB0);
- OLED_TWI_WriteByte(0x78, 0x00, 0x81);
- OLED_TWI_WriteByte(0x78, 0x00, 0xFF);
- OLED_TWI_WriteByte(0x78, 0x00, 0xA1);
- OLED_TWI_WriteByte(0x78, 0x00, 0xA6);
- OLED_TWI_WriteByte(0x78, 0x00, 0xA8);
- OLED_TWI_WriteByte(0x78, 0x00, 0x3F);
- OLED_TWI_WriteByte(0x78, 0x00, 0xC8);
- OLED_TWI_WriteByte(0x78, 0x00, 0xD3);
- OLED_TWI_WriteByte(0x78, 0x00, 0x00);
- OLED_TWI_WriteByte(0x78, 0x00, 0xD5);
- OLED_TWI_WriteByte(0x78, 0x00, 0x80);
- OLED_TWI_WriteByte(0x78, 0x00, 0xD8);
- OLED_TWI_WriteByte(0x78, 0x00, 0x05);
- OLED_TWI_WriteByte(0x78, 0x00, 0xD9);
- OLED_TWI_WriteByte(0x78, 0x00, 0xF1);
- OLED_TWI_WriteByte(0x78, 0x00, 0xDA);
- OLED_TWI_WriteByte(0x78, 0x00, 0x12);
- OLED_TWI_WriteByte(0x78, 0x00, 0xDB);
- OLED_TWI_WriteByte(0x78, 0x00, 0x30);
- OLED_TWI_WriteByte(0x78, 0x00, 0x8D);
- OLED_TWI_WriteByte(0x78, 0x00, 0x14);
- OLED_TWI_WriteByte(0x78, 0x00, 0xAF);
- }
复制代码
3.UART0底层驱动程序
UART0配置了中断方式,通过中断标志位,来实现发送数据完成的判断,接收到新数据的缓存操作……
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void ESP12_Init(void)
- {
- QUEUE_INIT();
- ESP12_InitBuffer();
- GPIO_Init(GPIO2, GPIO_PIN_0, GPIO_MODE_IN_PU);
- GPIO_Init(GPIO2, GPIO_PIN_1, GPIO_MODE_IN_PU);
- UART0_Init(32000000, 115200, UART0_Mode_10B, UART0_CLOCK_TIMER1, UART0_RX_ENABLE);
- UART0_ITConfig(ENABLE, LOW);
- TimeSliceStartup(ESP12_TxHandler, 5000);
- TimeSliceStartup(ESP12_RxHandler, 5);
- }
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void UART0_IRQHandler(void) interrupt 4
- {
- if (SET == UART0_GetFlagStatus(UART0_FLAG_RI))
- {
- QUEUE_PUSH(UART0_ReceiveData8());
- UART0_ClearFlag(UART0_FLAG_RI);
- }
- if (SET == UART0_GetFlagStatus(UART0_FLAG_TI))
- {
- UART0_ClearFlag(UART0_FLAG_TI);
- UART0_TI_Flag = 1;
- }
- }
复制代码
4.消息队列代码实现
使用消息队列是用来暂存UART0接收到的数据,对于接收到的数据不要中断函数中进行处理,而是先缓存起来,这样在接收大量数据时,保证了接收数据不会丢失(接收缓存大小满足的情况下),保证程序处理消息的正确性,随后在应用中对消息队列中的数据再进行解析处理……
- /* Private variables **************************************************************************************************/
- uint16_t ESP12_QueueFront = 0;
- uint16_t ESP12_QueueRear = 0;
- uint8_t ESP12_QueueData[600];
- /* Private functions **************************************************************************************************/
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void QUEUE_INIT(void)
- {
- ESP12_QueueFront = 0;
- ESP12_QueueRear = 0;
- memset(ESP12_QueueData, 0, sizeof(ESP12_QueueData));
- }
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- uint8_t QUEUE_EMPTY(void)
- {
- if (ESP12_QueueFront == ESP12_QueueRear)
- {
- return (1);
- }
- else
- {
- return (0);
- }
- }
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- uint8_t QUEUE_POP(void)
- {
- uint8_t Value = ESP12_QueueData[ESP12_QueueFront];
- ESP12_QueueFront += 1;
- ESP12_QueueFront %= 500;
- return (Value);
- }
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void QUEUE_PUSH(uint8_t Value)
- {
- ESP12_QueueData[ESP12_QueueRear] = Value;
- ESP12_QueueRear += 1;
- ESP12_QueueRear %= 500;
- }
复制代码
5.ESP-01 Wi-Fi驱动程序
ESP-01模块实现主要2部分,一部分是对于AT指令的处理,用于配置ESP-01模块的参数,比如连接Wi-Fi网络、连接服务器等;另一部分就是在与服务器建议通讯连接后,与服务器之间的消息通讯;这两部分都有不同的解析和处理方式,都是基于上述的消息队列来实现的……
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void ESP12_InitBuffer(void)
- {
- ESP12_Length = 0;
- memset(ESP12_Buffer, 0, sizeof(ESP12_Buffer));
- }
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- uint16_t ESP12_SendData(uint8_t Value)
- {
- uint16_t Timeout = ESP12_UART_TIMEOUT;
- UART0_TI_Flag = 0;
- UART0_SendData8(Value);
- while ((0 == UART0_TI_Flag) && (0 != Timeout))
- {
- Timeout--;
- }
- return (Timeout);
- }
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void ESP12_SendString(char *str)
- {
- while (*str)
- {
- ESP12_SendData(*str++);
- }
- }
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- uint8_t ESP12_AT_WaitForReply(char *Keyword)
- {
- while (QUEUE_EMPTY() == 0)
- {
- ESP12_Buffer[ESP12_Length++] = QUEUE_POP();
- if (strstr((char *)ESP12_Buffer, Keyword) != NULL)
- {
- return (1);
- }
- }
- return (0);
- }
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- uint16_t ESP12_AT_SendCommand(char *Command, char *Response, uint16_t Timeout)
- {
- if (Command != NULL)
- {
- QUEUE_INIT();
- ESP12_SendString(Command);
- ESP12_SendString("\r\n");
- }
- if (0 != Timeout)
- {
- ESP12_InitBuffer();
- while (Timeout--)
- {
- if (0 != ESP12_AT_WaitForReply(Response))
- {
- return (1);
- }
- TimeSliceDelayMS(1);
- }
- return (0);
- }
- return (1);
- }
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void ESP12_Configure(void)
- {
- uint8_t Result = 0;
- OLED_Clear();
- OLED_ShowString(0, 0, "Step:01", 16);
- OLED_ShowString(0, 2, "ESP12 Configure", 16);
- TimeSliceDelayMS(500);
- do
- {
- TimeSliceDelayMS(10);
- Result = ESP12_AT_SendCommand("AT", "OK", 100);
- } while (0 == Result);
- OLED_Clear();
- OLED_ShowString(0, 0, "Step:02", 16);
- OLED_ShowString(0, 2, "AT->OK", 16);
- TimeSliceDelayMS(500);
- /* 开回显 */
- ESP12_AT_SendCommand("ATE1", "OK", 100);
- OLED_Clear();
- OLED_ShowString(0, 0, "Step:03", 16);
- OLED_ShowString(0, 2, "ATE1", 16);
- TimeSliceDelayMS(500);
- /* 查询版本信息 */
- ESP12_AT_SendCommand("AT+GMR", "OK", 100);
- OLED_Clear();
- OLED_ShowString(0, 0, "Step:04", 16);
- OLED_ShowString(0, 2, "AT+GMR", 16);
- TimeSliceDelayMS(500);
- /* 设置当前Wi-Fi模式: Station模式 */
- ESP12_AT_SendCommand("AT+CWMODE=1", "OK", 100);
- OLED_Clear();
- OLED_ShowString(0, 0, "Step:05", 16);
- OLED_ShowString(0, 2, "Station Mode", 16);
- TimeSliceDelayMS(500);
- /* 连接WiFi */
- if (ESP12_AT_SendCommand("AT+CWJAP="********","********"", "OK", 8000) == 0)
- {
- if (ESP12_AT_SendCommand(NULL, "OK", 8000) == 0)
- {
- OLED_Clear();
- OLED_ShowString(0, 0, "WiFi Connect Error!", 16);
- return;
- }
- }
- OLED_Clear();
- OLED_ShowString(0, 0, "Step:06", 16);
- OLED_ShowString(0, 2, "WiFi Connect OK", 16);
- TimeSliceDelayMS(500);
- ESP12_WiFiFlag = 1;
- /* 查询IP地址 */
- ESP12_AT_SendCommand("AT+CIFSR", "OK", 100);
- OLED_Clear();
- OLED_ShowString(0, 0, "Step:07", 16);
- OLED_ShowString(0, 2, "Get IP", 16);
- TimeSliceDelayMS(500);
- /* 设置单链接 */
- ESP12_AT_SendCommand("AT+CIPMUX=0", "OK", 100);
- OLED_Clear();
- OLED_ShowString(0, 0, "Step:08", 16);
- OLED_ShowString(0, 2, "AT+CIPMUX=0", 16);
- TimeSliceDelayMS(500);
- /* 连接服务器 */
- if (ESP12_AT_SendCommand("AT+CIPSTART="TCP","api.seniverse.com",80", "OK", 8000) == 0)
- {
- OLED_Clear();
- OLED_ShowString(0, 0, "Server Connect Error!", 16);
- return;
- }
- OLED_Clear();
- OLED_ShowString(0, 0, "Step:09", 16);
- OLED_ShowString(0, 2, "Server Connect OK", 16);
- TimeSliceDelayMS(500);
- ESP12_ServerFlag = 1;
- /* 透明传输 */
- ESP12_AT_SendCommand("AT+CIPMODE=1", "OK", 100);
- OLED_Clear();
- OLED_ShowString(0, 0, "Step:10", 16);
- OLED_ShowString(0, 2, "AT+CIPMODE=1", 16);
- TimeSliceDelayMS(500);
- /* 开始传输 */
- if (ESP12_AT_SendCommand("AT+CIPSEND", ">", 1000) == 0)
- {
- OLED_Clear();
- OLED_ShowString(0, 0, "Transfer Not Ready...", 16);
- return;
- }
- OLED_Clear();
- OLED_ShowString(0, 0, "Step:11", 16);
- OLED_ShowString(0, 2, "Transfer Ready", 16);
- TimeSliceDelayMS(500);
- ESP12_InitFlag = 1;
- }
复制代码
6.OLED显示实时温度
OLED在配置ESP-01的步骤时,会进行相应的提示;在与知心天气服务器建立通讯后,会定期的向服务器发送获取信息的请求,服务器在收到请求后会核对信息和密钥,然后返回数据;返回的数据是JSON格式的,在C51中我们为了节省空间和操作,直接使用字符串的函数进行提取操作,并显示相应的信息到OLED显示屏上……
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void ESP12_TxHandler(void)
- {
- if (1 == ESP12_InitFlag)
- {
- /* 每间隔5秒获取一次天气信息, 服务器限制每分钟最多20次!!! */
- ESP12_SendString("GET https://api.seniverse.com/v3/weather/now.json?key=*****************&location=shanghai&language=zh-Hans&unit=c\r\n");
- }
- }
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void ESP12_RxHandler(void)
- {
- static uint8_t BraceCount = 0;
- static uint8_t BraceState = 0;
- uint8_t RxData = 0;
- if (0 == QUEUE_EMPTY())
- {
- if (0 == BraceState)
- {
- BraceState = 1;
- BraceCount = 0;
- ESP12_InitBuffer();
- }
- RxData = QUEUE_POP();
- ESP12_Buffer[ESP12_Length++] = RxData;
- switch (RxData)
- {
- case 0x7B:
- BraceCount++;
- break;
- case 0x7D:
- BraceCount--;
- if (0 == BraceCount)
- {
- BraceState = 2;
- }
- break;
- default:
- break;
- }
- if (ESP12_Length >= sizeof(ESP12_Buffer))
- {
- ESP12_Length = 0;
- }
- }
- else
- {
- if (2 == BraceState)
- {
- BraceState = 0;
- OLED_ShowString(0, 0, strstr((char *)ESP12_Buffer, ""temperature""), 16);
- }
- }
- }
复制代码
演示视频:
软件工程源代码:
Project_NBK-RD8x3x_NBK-EBS003.zip
(204.14 KB, 下载次数: 28)
|
评论
|