【原创干货】FRDM-K22F基于Kinetis SDK1.1的I2C通信HAL层例程
羊年伊始,假期结束,重新回到了工作岗位。回味过去的一整年,成长不少,收获良多,感恩身边的人。展望新的一年征程,充满未知和挑战,收拾心情,整装待发,奋斗ing…
闲话不多说了,直接说正事吧。飞思卡尔去年终于推出了好多人都翘首以盼的底层驱动库Kinetis SDK,看名字就知道了,这个驱动库主要是针对飞思卡尔ARM家族Kinetis系列的了,目前已经更新到v1.1版本了。针对该驱动库的具体介绍在这篇文章里我就不赘述了,建议大家直接到飞思卡尔的官网去仔细查阅和下载,其官方链接为http://www.freescale.com/zh-Hans/webapp/sps/site/prod_summary.jsp?code=KINETIS_SDK&fsrch=1&sr=3&pageNum=1&uc=true&lang_cd=zh-Hans,当然,刚开始支持的芯片系列有限,不过随着版本的不多更新,会有越来越多的芯片被添加进来。
本篇文章的主要目的是给出一个基于SDK HAL层的I2C通信例程供参考移植,毕竟用到I2C的地方还是比较多的,像外扩EEPROM,电源管理芯片等都需要与主MCU进行I2C通信。所以那怎样基于SDK编写HAL层的I2C驱动代码呢,虽然SDK里面自带Demo例程里已经有I2C的Driver层驱动了,但是Drvier层有其自身局限性(实现的形式和功能比较固定,一般作为演示用例还好),而HAL层则灵活的多(HAL层实际上就是对底层寄存器进行了封装,屏蔽了硬件的兼容问题),使用HAL层可以最大程度的利用外设模块。FRDM-K22板子上自带了一个飞思卡尔自家的6轴传感器E-Compass(3轴加速度+3轴地磁),通信接口为I2C和SPI接口可选,本篇博客既然以I2C为例介绍,所以就选择I2C接口,板子上已经将该传感器与MCU连好了,并且加了上拉电阻,所以硬件工作无需额外了,只需要在软件上下功夫就可以了,下面我简单介绍下开发平台和开发环境:
开发平台:FRDM-K22F,板载传感器的从机地址为0x1C,通信波特率为90kbps
开发环境:IAR 7.3
例程模板:KSDK_1.1.0\demos\hello_world\iar\frdmk22f
需要提一下的是,我写的代码是在SDK1.1中的Hello world例程的基础上修改的,修改后的代码我已上传到博客最后的附件中,将附件中.c文件的所有内容覆盖原来的在SDK1.1安装目录下hello_world例程的hello_world.c文件中的所有内容即可,然后编译并下载到板子上,运行PC端的串口调试助手或者超级终端(串口波特率为115200),复位MCU,此时会打印出"Hello World!”,然后向板子发送任意一个字符即可输出板载传感器6个轴向的数据,如下图:
好了,就说到这了,由于附件的代码里我已经都做了相应的注释,所以就不在博客里一一去剖析解释了(实在是有点麻烦,呵呵),我相信看完代码就都明白了,呵呵。
(附加代码↓)
/*
* Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
///////////////////////////////////////////////////////////////////////////////
// Includes
///////////////////////////////////////////////////////////////////////////////
// Standard C Included Files
#include <stdio.h>
#include <stdlib.h>
// SDK Included Files
#include "board.h"
#include "fsl_debug_console.h"
#include "fsl_i2c_hal.h"
#include "fsl_device_registers.h"
#include "fsl_clock_manager.h"
////////////////////////////////////////////////////////////////////////////////
// Code
////////////////////////////////////////////////////////////////////////////////
#define WHO_AM_I_REG 0x0D
#define CTRL_REG1 0x2A
#define XYZ_DATA_CFG 0x0E
#define M_CTRL_REG1 0x5B
#define M_CTRL_REG2 0x5C
#define OUT_X_MSB 0x01
#define WHO_AM_I_MASK 0xC7
#define ACTIVE_MASK 0x01
void I2C_Init(void);
void FXOS8700_Init(void);
i2c_status_t Hal_Dev_FXOS8700_Read_Reg(uint8_t addr, uint8_t *Buff, uint8_t len);
i2c_status_t Hal_Dev_FXOS8700_Write_Reg(uint8_t addr, uint8_t data);
typedef struct
{
int16_t x;
int16_t y;
int16_t z;
} SRAWDATA;
int main (void)
{
// RX buffers
//! @param receiveBuff Buffer used to hold received data
uint8_t receiveBuff;
uint8_t Buffer_Temp[12];
SRAWDATA AccelData, MagnData;
// Initialize standard SDK demo application pins
hardware_init();
// Call this function to initialize the console UART. This function
// enables the use of STDIO functions (printf, scanf, etc.)
dbg_uart_init();
configure_i2c_pins(BOARD_FXOS8700_I2C_INSTANCE);
FXOS8700_Init();
// Print the initial banner
PRINTF("\r\nHello World!\n\n\r");
while(1)
{
// First, get character
receiveBuff = GETCHAR();
Hal_Dev_FXOS8700_Read_Reg(OUT_X_MSB, Buffer_Temp, 12);
// copy the 14 bit accelerometer byte data into 16 bit words
AccelData.x = (int16_t)(((Buffer_Temp[0] << 8) | Buffer_Temp[1]))>> 2;
AccelData.y = (int16_t)(((Buffer_Temp[2] << 8) | Buffer_Temp[3]))>> 2;
AccelData.z = (int16_t)(((Buffer_Temp[4] << 8) | Buffer_Temp[5]))>> 2;
// copy the magnetometer byte data into 16 bit words
MagnData.x = (Buffer_Temp[6] << 8) | Buffer_Temp[7];
MagnData.y = (Buffer_Temp[8] << 8) | Buffer_Temp[9];
MagnData.z = (Buffer_Temp[10] << 8) | Buffer_Temp[11];
// Printf the Accelerometer and Magnetometer's information
PRINTF("The Accelerometer x-value: %d\n\r", AccelData.x);
PRINTF("The Accelerometer y-value: %d\n\r", AccelData.y);
PRINTF("The Accelerometer z-value: %d\n\r", AccelData.z);
PRINTF("The Magnetometer x-value: %d\n\r", MagnData.x);
PRINTF("The Magnetometer y-value: %d\n\r", MagnData.y);
PRINTF("The Magnetometer z-value: %d\n\r", MagnData.z);
}
}
void I2C_Init(void)
{
CLOCK_SYS_EnableI2cClock(BOARD_FXOS8700_I2C_INSTANCE);
I2C_HAL_Init(I2C0_BASE);
I2C_HAL_SetAddress7bit(I2C0_BASE, 0x3A);
I2C_HAL_SetBaudRate(I2C0_BASE, CLOCK_SYS_GetBusClockFreq(), 90, NULL);
I2C_HAL_Enable(I2C0_BASE);
}
void FXOS8700_Init(void)
{
uint8_t deviceWhoAmI = 0;
I2C_Init();
// Verify device is there
Hal_Dev_FXOS8700_Read_Reg(WHO_AM_I_REG, &deviceWhoAmI, 1);
if (deviceWhoAmI != WHO_AM_I_MASK)
{
PRINTF("The Initilaztion Error!\n\r");
}
Hal_Dev_FXOS8700_Write_Reg(CTRL_REG1, 0);
Hal_Dev_FXOS8700_Write_Reg(M_CTRL_REG1, 0x1F);
Hal_Dev_FXOS8700_Write_Reg(M_CTRL_REG2, 0x20);
Hal_Dev_FXOS8700_Write_Reg(XYZ_DATA_CFG, 0x01);
Hal_Dev_FXOS8700_Write_Reg(CTRL_REG1, 0x0D);
}
i2c_status_t Hal_Dev_FXOS8700_Read_Reg(uint8_t addr, uint8_t *Buff, uint8_t len)
{
return(I2C_HAL_MasterReceiveDataPolling(I2C0_BASE, BOARD_FXOS8700_I2C_ADDR, &addr, 1, Buff, len));
}
i2c_status_t Hal_Dev_FXOS8700_Write_Reg(uint8_t addr, uint8_t data)
{
return(I2C_HAL_MasterSendDataPolling(I2C0_BASE, BOARD_FXOS8700_I2C_ADDR, &addr, 1, &data, 1));
}