【MCXN947开发板测评】I2C总线设备的兼容性测试
[复制链接]
1、测试简介
测试如何使用 CMSIS i2c 驱动作为主机,通过I2C总线控制SSD1306 OLED显示图像。通过轮询方式进行I2C控制通讯。
硬件要求:
Type-C USB 线
FRDM - MCXN947 开发板
SSD1306 OLED屏
个人计算机
软件:
GCC ARM 嵌入式 13.2.1
Putty串口终端
2、设置与程序
OLED屏需按以下方式连接:
主机(LPI2C2) 连接 SSD1306
开发板 OLED
SCL J2 引脚 20 <----------> SCL
SDA J2 引脚 18 <----------> SDA
GND J3 引脚 14 <----------> GND
P3.3V J3 引脚 4 <----------> 3.3V
/*
* Copyright 2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/* Standard C Included Files */
#include <stdio.h>
#include <string.h>
#include "pin_mux.h"
#include "clock_config.h"
#include "board.h"
#include "fsl_debug_console.h"
#include "fsl_lpi2c.h"
#include "fsl_SSD1306_I2C.h"
/*******************************************************************************
* Definitions
******************************************************************************/
//#define EXAMPLE_I2C_MASTER_BASE (LPI2C2_BASE)
#define LPI2C_MASTER_CLOCK_FREQUENCY CLOCK_GetLPFlexCommClkFreq(2u)
#define WAIT_TIME 10U
//#define EXAMPLE_I2C_MASTER ((LPI2C_Type *)EXAMPLE_I2C_MASTER_BASE)
#define LPI2C_MASTER_SLAVE_ADDR_7BIT 0x3CU
#define LPI2C_BAUDRATE 100000U
#define LPI2C_DATA_LENGTH 33U
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
uint8_t g_master_txBuff[LPI2C_DATA_LENGTH];
uint8_t g_master_rxBuff[LPI2C_DATA_LENGTH];
/*******************************************************************************
* Code
******************************************************************************/
/*!
* [url=home.php?mod=space&uid=159083]@brief[/url] Main function
*/
int main(void)
{
lpi2c_master_config_t masterConfig;
//status_t reVal = kStatus_Fail;
//uint8_t deviceAddress = 0x01U;
size_t txCount = 0xFFU;
/* attach FRO 12M to FLEXCOMM4 (debug console) */
CLOCK_SetClkDiv(kCLOCK_DivFlexcom4Clk, 1u);
CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH);
/* attach FRO 12M to FLEXCOMM2 */
CLOCK_SetClkDiv(kCLOCK_DivFlexcom2Clk, 1u);
CLOCK_AttachClk(kFRO12M_to_FLEXCOMM2);
BOARD_InitBootPins();
BOARD_InitBootClocks();
BOARD_InitDebugConsole();
PRINTF("\r\nLPI2C board2board polling example -- Master transfer.\r\n");
LPI2C_MasterGetDefaultConfig(&masterConfig);
/* Change the default baudrate configuration */
masterConfig.baudRate_Hz = LPI2C_BAUDRATE;
/* Initialize the LPI2C master peripheral */
LPI2C_MasterInit(EXAMPLE_I2C_MASTER, &masterConfig, LPI2C_MASTER_CLOCK_FREQUENCY);
/* Initialize the SSD1306 display*/
OLED_Init();
OLED_Refresh();
OLED_Clear();
/*Print welcome message*/
OLED_Copy_Image(&logo_nxp[0], sizeof(logo_nxp));
OLED_Refresh();
OLED_Set_Text(10, 52, kOLED_Pixel_Set, "MCXN947 I2C", 2);
OLED_Refresh();
PRINTF("\r\nEnd of LPI2C example .\r\n");
while (1)
{
}
}
OLED SSD1306驱动程序fsl_SSD1306_I2C.c
/*----esta modificada para usar el I2C1, en caso de utilizar otro cambiar todo
* lo que diga I2C1 por la base del I2C usado--- */
/*---- BASADO EN fsl_SSD1306.h para SPI de NXP ------*/
#include "fsl_gpio.h"
#include "fsl_lpi2c.h"
#include <fsl_SSD1306_I2C.h>
// #include "fsl_Systick_Delay.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief OLED buffer */
static uint8_t OLED_Buffer[(OLED_WIDTH * OLED_HEIGHT) / 8];
/*******************************************************************************
* Code
******************************************************************************/
static void OLED_Command(uint8_t Cmd) {
lpi2c_master_transfer_t xfer = {0};
xfer.data = (uint8_t *)&Cmd;
xfer.dataSize = sizeof(Cmd);
xfer.flags = kLPI2C_TransferDefaultFlag;
xfer.slaveAddress = SSD1306_ADDRESS_1;
xfer.direction = kLPI2C_Write;
xfer.subaddress = 0x0;
xfer.subaddressSize = 1;
LPI2C_MasterTransferBlocking(EXAMPLE_I2C_MASTER, &xfer);
}
static void OLED_Data(uint8_t *Data) {
lpi2c_master_transfer_t xfer = {0};
/*Start Transfer*/
xfer.data = Data;
xfer.dataSize = sizeof(OLED_Buffer);
xfer.flags = kLPI2C_TransferDefaultFlag;
xfer.slaveAddress = SSD1306_ADDRESS_1;
xfer.direction = kLPI2C_Write;
xfer.subaddress = 0x40;
xfer.subaddressSize = 1;
LPI2C_MasterTransferBlocking(EXAMPLE_I2C_MASTER, &xfer);
}
static void OLED_Reset(void) {
OLED_Command(OLED_DISPLAYON);
// for(int i=0; i<5000; i++); //delay
//1ms
// SysTick_Delay_ms(1);
OLED_Command(OLED_DISPLAYOFF);
// for(int i=0; i<5000; i++); //delay
//1ms
// SysTick_Delay_ms(1);
OLED_Command(OLED_DISPLAYON);
// for(int i=0; i<50000; i++); //delay
//10ms
// SysTick_Delay_ms(10);
}
static void OLED_Config_Display(void) {
OLED_Reset();
// Turn the OLED Display off
OLED_Command(OLED_DISPLAYOFF);
// Configure the display for 128x64 pixels, KS0108 mode
OLED_Command(OLED_SETDISPLAYCLOCKDIV);
OLED_Command(0x80);
OLED_Command(OLED_SETMULTIPLEX);
OLED_Command(OLED_HEIGHT - 1); // LCD Height
OLED_Command(OLED_SETDISPLAYOFFSET);
OLED_Command(0x0);
OLED_Command(OLED_SETSTARTLINE | 0x0);
OLED_Command(OLED_CHARGEPUMP);
OLED_Command(0x14); // Use 3.3V supply to generate high voltage supply
OLED_Command(OLED_MEMORYMODE);
OLED_Command(0x00);
OLED_Command(OLED_SEGREMAP | 0x1);
OLED_Command(OLED_COMSCANDEC);
OLED_Command(OLED_SETCOMPINS);
OLED_Command(0x12);
OLED_Command(OLED_SETCONTRAST);
OLED_Command(0xCF);
OLED_Command(OLED_SETPRECHARGE);
OLED_Command(0xF1);
OLED_Command(OLED_SETVCOMDETECT);
OLED_Command(0x40);
OLED_Command(OLED_DISPLAYALLON_RESUME);
OLED_Command(OLED_NORMALDISPLAY);
OLED_Command(OLED_DEACTIVATE_SCROLL);
OLED_Command(OLED_COLUMNADDR);
OLED_Command(0);
OLED_Command(OLED_WIDTH - 1);
OLED_Command(OLED_PAGEADDR);
OLED_Command(0);
OLED_Command(OLED_HEIGHT / 8 - 1);
// Turn the OLED display on!
OLED_Command(OLED_DISPLAYON);
OLED_Command(OLED_SETLOWCOLUMN | 0x0); // low col = 0
OLED_Command(OLED_SETHIGHCOLUMN | 0x0); // hi col = 0
OLED_Command(OLED_SETSTARTLINE | 0x0); // line #0
}
static int OLED_Render_Char(uint8_t X_axis, uint8_t Y_axis, uint8_t SC,
int8_t String, uint8_t Scale) {
uint8_t px, py;
uint16_t start_pos;
if ((X_axis >= OLED_WIDTH) || (Y_axis >= OLED_HEIGHT)) {
return 1;
}
if (String > 127) {
return 2;
}
if (Scale > 3) {
return 3;
}
start_pos = ((uint8_t)String) * 7; // Characters have a 7 row offset
for (px = 0; px < 5; px++) {
for (py = 0; py < 7; py++) {
if ((font5x7[start_pos + py] >> (7 - px)) & 1) {
switch (Scale) {
case 3:
OLED_Set_Pixel(X_axis + (px * Scale), Y_axis + (py * Scale), SC);
OLED_Set_Pixel(X_axis + (px * Scale) + 1, Y_axis + (py * Scale), SC);
OLED_Set_Pixel(X_axis + (px * Scale) + 2, Y_axis + (py * Scale), SC);
OLED_Set_Pixel(X_axis + (px * Scale), Y_axis + (py * Scale) + 1, SC);
OLED_Set_Pixel(X_axis + (px * Scale) + 1, Y_axis + (py * Scale) + 1,
SC);
OLED_Set_Pixel(X_axis + (px * Scale) + 2, Y_axis + (py * Scale) + 1,
SC);
OLED_Set_Pixel(X_axis + (px * Scale), Y_axis + (py * Scale) + 2, SC);
OLED_Set_Pixel(X_axis + (px * Scale) + 1, Y_axis + (py * Scale) + 2,
SC);
OLED_Set_Pixel(X_axis + (px * Scale) + 2, Y_axis + (py * Scale) + 2,
SC);
break;
case 2:
OLED_Set_Pixel(X_axis + (px * Scale), Y_axis + (py * Scale), SC);
OLED_Set_Pixel(X_axis + (px * Scale) + 1, Y_axis + (py * Scale), SC);
OLED_Set_Pixel(X_axis + (px * Scale), Y_axis + (py * Scale) + 1, SC);
OLED_Set_Pixel(X_axis + (px * Scale) + 1, Y_axis + (py * Scale) + 1,
SC);
break;
case 1:
default:
OLED_Set_Pixel(X_axis + px, Y_axis + py, SC);
break;
}
}
}
}
return 0;
}
void OLED_Init(void) {
/*Give the display a reset*/
OLED_Reset();
/* Clear the framebuffer*/
OLED_Clear();
/*Configure the OLED display controller*/
OLED_Config_Display();
}
void OLED_Refresh(void) {
OLED_Command(0xb0);
OLED_Command(((0 & 0xf0) >> 4) | 0x10);
OLED_Command((0 & 0x0f) | 0x01);
OLED_Data(&OLED_Buffer[0]);
}
void OLED_Clear(void) { memset(OLED_Buffer, 0, sizeof(OLED_Buffer)); }
void OLED_Fill(uint8_t Pattern) {
memset(OLED_Buffer, Pattern, sizeof(OLED_Buffer));
}
void OLED_Display_Mode(uint8_t Mode) {
if (Mode) {
OLED_Command(OLED_INVERTDISPLAY);
} else {
OLED_Command(OLED_NORMALDISPLAY);
}
}
void OLED_Set_Pixel(uint8_t X_axis, uint8_t Y_axis, uint8_t SC) {
if ((X_axis >= OLED_WIDTH) || (Y_axis >= OLED_HEIGHT)) {
// Do nothing
} else {
switch (SC) {
case kOLED_Pixel_Clear:
OLED_Buffer[X_axis + (Y_axis / 8) * OLED_WIDTH] &= ~(1 << (Y_axis & 7));
break;
case kOLED_Pixel_Set:
OLED_Buffer[X_axis + (Y_axis / 8) * OLED_WIDTH] |= (1 << (Y_axis & 7));
break;
}
}
}
void OLED_Set_Text(uint8_t X_axis, uint8_t Y_axis, uint8_t SC, char *String,
uint8_t Scale) {
uint16_t Cont;
uint16_t xscaled;
if ((X_axis >= OLED_WIDTH) || (Y_axis >= OLED_HEIGHT)) {
// Do nothing
} else {
if (Scale > 3) {
// Do nothing
} else {
for (Cont = 0; String[Cont] != '\0'; Cont++) {
// Catch overflow when scaling!
xscaled = X_axis + (Cont * 5 * Scale);
if (xscaled > OLED_WIDTH) {
// Do nothing
}
else {
OLED_Render_Char(xscaled, Y_axis, SC, String[Cont], Scale);
}
}
}
}
}
void OLED_Copy_Image(const uint8_t *Img, uint16_t size) {
uint16_t CpyBuffer;
OLED_Clear();
for (CpyBuffer = 0; CpyBuffer < size - 1; CpyBuffer++) {
OLED_Buffer[CpyBuffer] = *(Img + CpyBuffer);
}
}
3、测试过程
将开发板与OLED相连接
4、总结
MCXN的I2C编程使用查询模式对MCU不断查询。所以对于MCU有一定的压力,对于双核的系统可以发挥效能。
|