Linux-Ubuntu之SPI串行通信陀螺仪和加速度计
Linux-Ubuntu之SPI串口通信陀螺仪和加速度计
- 一,SPI通信原理
- 二,ICM-20608六轴传感器控制
- 三,代码
- 1.小tip
一,SPI通信原理
SPI:串行全双工通信,最高能达到百MHZ,通常一个主设备跟多个从设备,标准是4线模式,CS片选,SCK串行时钟,MOSI主发从收,MISO从发主收,能实现全双工就是因为有两根单独的数据线。对于I2C通信,I2C只有SCL和SDA时钟和数据线,不同点:①属于半双工,②通信速度上,I2C最高400KHZ,没有SPI快,③在从机设备选择上,SPI有片选信号线,从机拉低该信号线,主机就能和该从机通信,I2C是通过在数据中发送从机的地址,选择从机设备。相同点:①都是串行通信,数据按位传输,②都是主从架构,一个主设备作为控制中心,多个从设备响应并进行数据的传输。
SPI通过串行时钟极性(CPOL)和相位(CPHA)的搭配来得到四种工作模式四种工作模式,CPOL为0,空闲的时候时钟线位低电平,为1的时候,空闲为高电平,CPHA,为0第一个上升沿或者下降沿就开始数据的采集,为1第二个上升沿或者下降沿开始数据采集。
工作采用CPOL=0,CPHA=0 ,低电平空闲状态,遇到第一个上升沿,开始数据采集,传输1bit,再遇到下一个上升沿,再传输1bit。
二,ICM-20608六轴传感器控制
ICM20608整体程序包括三部分:1.对引脚初始化,由于片选信号用的是GPIO1-IO20,对其初始化还包括设置软件的片选,设置为输出模式,在读取数据时,对这个IO进行写0、写1操作实现软件控制片选,当然要先设置硬件片选上与这个IO连接。2.对SPI的初始化,直接调用SPI中的函数即可,并关闭休眠模式。3.这部分是真实对这个传感器的寄存器数据进行读写的函数,调用SPI中的读写函数,并且在该部分带入寄存器的值,即可实现对寄存器数据的读写,并且调用函数将寄存器中的数据,转化为正常能看懂的值。
读取的数据包括加速度、陀螺仪值和芯片温度,程序其实和I2C的类似,先在SPI的函数中,进行对SPI相关寄存器初始化,包括使能,设置写入寄存器后寄存器发送,设置通道,时钟分频以及其他先关寄存器配置,再说明读写函数,这个读写函数比I2C简单,发送时:直接判断寄存器状态是否为空,空了就往RXDATA中写数据,自动就实现数据发送,接收时:判断寄存器状态是否来数据了,来了数据就将RXDATA中的数据读取。
三,代码
/*spi.h*/
#ifndef _DSP_SPI_H
#define _DSP_SPI_H
#include "imx6ul.h"
/*spi的初始化*/
void spi_init(ECSPI_Type *base);
/*SPI发送接收函数*/
unsigned char spi_read_and_write_byte(ECSPI_Type *base,unsigned char txdata);
#endif
/*spi.c*/
#include "dsp_spi.h"
/*spi的初始化*/
void spi_init(ECSPI_Type *base)
{
base->CONREG = 0;//清0
base->CONREG |=(1<<0)|(1<<3)|(1<<4)|(7<<20);//使能SPI 设置写入数据后发送数据 通道0 8bit突发
base->CONFIGREG = 0;
base->PERIODREG = 0x2000;
/*SPI时钟分频*/
base->CONREG &=~((0xf<<12)|(0xf<<8));//清0
base->CONREG |=(0x9<<12);//设置分频10 60MHZ/10=6MHZ
}
/*SPI发送接收函数*/
unsigned char spi_read_and_write_byte(ECSPI_Type *base,unsigned char txdata)
{
uint32_t spi_rxdata = 0;
uint32_t spi_txdata = txdata;
/*通道0*/
base->CONREG &=~(3<<18);
base->CONREG |=(0<<18);
/*数据发送*/
while((base->STATREG & (1<<0))==0){};
base->TXDATA = spi_txdata;
/*数据接收*/
while((base->STATREG & (1<<3))==0){};
spi_rxdata = base->RXDATA;
return spi_rxdata;
}
/*icm20608.c*/
#include "dsp_icm20608.h"
#include "dsp_spi.h"
#include "dsp_delay.h"
#include "stdio.h"
struct icm20608_dev_struc icm20608_dev; /* icm20608设备 */
/*icm20608初始化*/
void icm20608_init(void)
{
// unsigned char vallll;
// vallll = icm20608_read_reg(ICM20_WHO_AM_I);
/*1.引脚初始化*/
IOMUXC_SetPinMux(IOMUXC_UART2_RX_DATA_ECSPI3_SCLK,0);//ECSPI3_SCLK
IOMUXC_SetPinConfig(IOMUXC_UART2_RX_DATA_ECSPI3_SCLK,0X10b1);
IOMUXC_SetPinMux(IOMUXC_UART2_CTS_B_ECSPI3_MOSI,0); //主输出 从输入
IOMUXC_SetPinConfig(IOMUXC_UART2_CTS_B_ECSPI3_MOSI,0X10b1);
IOMUXC_SetPinMux(IOMUXC_UART2_RTS_B_ECSPI3_MISO,0); //主输入 从输出
IOMUXC_SetPinConfig(IOMUXC_UART2_RTS_B_ECSPI3_MISO,0X10b1);
IOMUXC_SetPinMux(IOMUXC_UART2_TX_DATA_GPIO1_IO20,0); //片选
IOMUXC_SetPinConfig(IOMUXC_UART2_TX_DATA_GPIO1_IO20,0X10b0);
gpio_config_t CS_config;
CS_config.section= gpio_out;
CS_config.mode=0;
gpio_init(GPIO1,20,&CS_config);
/*2.spi初始化*/
spi_init(ECSPI3);
icm20608_write_reg(ICM20_PWR_MGMT_1, 0x80);//打开休眠模式
delay(50);
icm20608_write_reg(ICM20_PWR_MGMT_1, 0x01);//关闭休眠模式
delay(50);
/*3.icm20608内部寄存器设置,即初始化*/
icm20608_write_reg(ICM20_SMPLRT_DIV,0X00);//输出数率是采样率
icm20608_write_reg(ICM20_GYRO_CONFIG,0X18);//陀螺仪量程2000
icm20608_write_reg(ICM20_ACCEL_CONFIG,0X18);//加速度16
icm20608_write_reg(ICM20_CONFIG,0x04);
icm20608_write_reg(ICM20_ACCEL_CONFIG2, 0x04);
icm20608_write_reg(ICM20_PWR_MGMT_2, 0x00);
icm20608_write_reg(ICM20_LP_MODE_CFG, 0x00);
icm20608_write_reg(ICM20_FIFO_EN, 0x00);
}
/*进行读寄存器数据*/
unsigned char icm20608_read_reg(unsigned char reg_address)
{
unsigned char result;
reg_address |=0x80;//最高为值置1,表示进行读数据
IMC20608_CSN(0);//片选拉低
spi_read_and_write_byte(ECSPI3,reg_address);//先写入寄存器地址
result=spi_read_and_write_byte(ECSPI3,0xff);//进行读操作,后面跟的数据没什么用,读的是RXDATA中第数据
IMC20608_CSN(1);//片选拉高
return result;
}
/*进行写寄存器数据*/
void icm20608_write_reg(unsigned char reg_address,unsigned char reg_in_data)
{
reg_address &=~(1<<8);//最高为值置0,表示进行写数据
IMC20608_CSN(0);//片选拉低
spi_read_and_write_byte(ECSPI3,reg_address);//先写入寄存器地址
spi_read_and_write_byte(ECSPI3,reg_in_data);//进行写操作,先写寄存器地址,再写数据
IMC20608_CSN(1);//片选拉高
}
/*加速度计计算需要的值*/
unsigned short icm20608_accel_scaleget(void)
{
unsigned char data;
unsigned short accelscale;
data = (icm20608_read_reg(ICM20_ACCEL_CONFIG) >> 3) & 0X3;
switch(data) {
case 0:
accelscale = 16384;
break;
case 1:
accelscale = 8192;
break;
case 2:
accelscale = 4096;
break;
case 3:
accelscale = 2048;
break;
}
return accelscale;
}
/*陀螺仪计算需要的值*/
float icm20608_gyro_scaleget(void)
{
unsigned char data;
float gyroscale;
data = (icm20608_read_reg(ICM20_GYRO_CONFIG) >> 3) & 0X3;
switch(data) {
case 0:
gyroscale = 131;
break;
case 1:
gyroscale = 65.5;
break;
case 2:
gyroscale = 32.8;
break;
case 3:
gyroscale = 16.4;
break;
}
return gyroscale;
}
/*读多个寄存器值*/
void icm20608_read_more(unsigned char reg,unsigned char *buf,unsigned char len)
{
unsigned int i=0;
reg |=0x80;//设置为读模式
IMC20608_CSN(0);//使能
spi_read_and_write_byte(ECSPI3,reg);//先写入寄存器地址
for(i=0;i<len;i++)
{
buf[i]=spi_read_and_write_byte(ECSPI3,0xff);//??
}
IMC20608_CSN(1);//关闭使能
}
/*获取数据*/
void icm20608_get_data(void)
{
unsigned char data[14];
icm20608_read_more(ICM20_ACCEL_XOUT_H,data,14);//真神奇,能够一直往地址加一的寄存器读取数据
float gyroscale=icm20608_gyro_scaleget();
unsigned short accescale=icm20608_accel_scaleget();
icm20608_dev.accel_x_adc=(signed short)((data[0]<<8)|data[1]);
icm20608_dev.accel_y_adc=(signed short)((data[2]<<8)|data[3]);
icm20608_dev.accel_z_adc=(signed short)((data[4]<<8)|data[5]);
icm20608_dev.temp_adc=(signed short)((data[6]<<8)|data[7]);
icm20608_dev.gyro_x_adc=(signed short)((data[8]<<8)|data[9]);
icm20608_dev.gyro_y_adc=(signed short)((data[10]<<8)|data[11]);
icm20608_dev.gyro_z_adc=(signed short)((data[12]<<8)|data[13]);
/*转换为实际值*/
icm20608_dev.gyro_x_act = ((float)(icm20608_dev.gyro_x_adc) / gyroscale) * 100;
icm20608_dev.gyro_y_act = ((float)(icm20608_dev.gyro_y_adc) / gyroscale) * 100;
icm20608_dev.gyro_z_act = ((float)(icm20608_dev.gyro_z_adc) / gyroscale) * 100;
icm20608_dev.accel_x_act = ((float)(icm20608_dev.accel_x_adc) / accescale) * 100;
icm20608_dev.accel_y_act = ((float)(icm20608_dev.accel_y_adc) / accescale) * 100;
icm20608_dev.accel_z_act = ((float)(icm20608_dev.accel_z_adc) / accescale) * 100;
icm20608_dev.temp_act = (((float)(icm20608_dev.temp_adc) - 25 ) / 326.8 + 25) * 100;
}
/*icm20608.h*/
#ifndef _DSP_ICM20608_H
#define _DSP_ICM20608_H
#include "imx6ul.h"
#include "dsp_gpio.h"
#define IMC20608_CSN(n) (n ? gpio_write(GPIO1,20,1):gpio_write(GPIO1,20,0)) //n濞戞搫鎷�1闁告劧鎷�1 濞戞搫鎷�0闁告劧鎷�0
#define ICM20608G_ID 0XAF
#define ICM20608D_ID 0XAE
/* 闂傚嫷婢侀幏鐑芥懚鏉炴澘宕曢柛婊冭嫰婵偤鏌呴悢宄邦唺闁煎浜濈粊锟�(闁告垼妗ㄦ鍥籍閹偊鍟庣紓鍐惧櫙缁辨繈鎮介妸銈囪壘濞戞挸娴烽弫銈夊箣妞嬪孩鐣遍柤濂変簼椤ュ懏娼忛幘鍐叉瘔闁稿﹤鍚嬮惁顔芥綇閸愯法绀� */
#define ICM20_SELF_TEST_X_GYRO 0x00
#define ICM20_SELF_TEST_Y_GYRO 0x01
#define ICM20_SELF_TEST_Z_GYRO 0x02
#define ICM20_SELF_TEST_X_ACCEL 0x0D
#define ICM20_SELF_TEST_Y_ACCEL 0x0E
#define ICM20_SELF_TEST_Z_ACCEL 0x0F
/* 闂傚嫷婢侀幏鐑芥懚鏉炴澘宕曢梻鍫熺懕閹风兘鏁撻挊澶夌剨缂佸鎷�1闁跨噦鎷�7 */
#define ICM20_XG_OFFS_USRH 0x13
#define ICM20_XG_OFFS_USRL 0x14
#define ICM20_YG_OFFS_USRH 0x15
#define ICM20_YG_OFFS_USRL 0x16
#define ICM20_ZG_OFFS_USRH 0x17
#define ICM20_ZG_OFFS_USRL 0x18
#define ICM20_SMPLRT_DIV 0x19
#define ICM20_CONFIG 0x1A
#define ICM20_GYRO_CONFIG 0x1B
#define ICM20_ACCEL_CONFIG 0x1C
#define ICM20_ACCEL_CONFIG2 0x1D
#define ICM20_LP_MODE_CFG 0x1E
#define ICM20_ACCEL_WOM_THR 0x1F
#define ICM20_FIFO_EN 0x23
#define ICM20_FSYNC_INT 0x36
#define ICM20_INT_PIN_CFG 0x37
#define ICM20_INT_ENABLE 0x38
#define ICM20_INT_STATUS 0x3A
/* 闁告梻濯撮幏鐑芥晸閽樺顔婇弶鍫熸尭閸わ拷 */
#define ICM20_ACCEL_XOUT_H 0x3B
#define ICM20_ACCEL_XOUT_L 0x3C
#define ICM20_ACCEL_YOUT_H 0x3D
#define ICM20_ACCEL_YOUT_L 0x3E
#define ICM20_ACCEL_ZOUT_H 0x3F
#define ICM20_ACCEL_ZOUT_L 0x40
/* 婵炴挴鏅涚€硅櫕娼忛幘鍐叉瘔 */
#define ICM20_TEMP_OUT_H 0x41
#define ICM20_TEMP_OUT_L 0x42
/* 闂傚嫷婢侀幏鐑芥懚鏉炴澘宕曢弶鍫熸尭閸わ拷 */
#define ICM20_GYRO_XOUT_H 0x43
#define ICM20_GYRO_XOUT_L 0x44
#define ICM20_GYRO_YOUT_H 0x45
#define ICM20_GYRO_YOUT_L 0x46
#define ICM20_GYRO_ZOUT_H 0x47
#define ICM20_GYRO_ZOUT_L 0x48
#define ICM20_SIGNAL_PATH_RESET 0x68
#define ICM20_ACCEL_INTEL_CTRL 0x69
#define ICM20_USER_CTRL 0x6A
#define ICM20_PWR_MGMT_1 0x6B
#define ICM20_PWR_MGMT_2 0x6C
#define ICM20_FIFO_COUNTH 0x72
#define ICM20_FIFO_COUNTL 0x73
#define ICM20_FIFO_R_W 0x74
#define ICM20_WHO_AM_I 0x75
#define ICM20_XA_OFFSET_H 0x77
#define ICM20_XA_OFFSET_L 0x78
#define ICM20_YA_OFFSET_H 0x7A
#define ICM20_YA_OFFSET_L 0x7B
#define ICM20_ZA_OFFSET_H 0x7D
#define ICM20_ZA_OFFSET_L 0x7E
/*
* ICM20608缂備焦鎸婚悗顖涙媴閿燂拷1闁跨噦鎷�7
*/
struct icm20608_dev_struc
{
signed int gyro_x_adc; /* 闂傚嫷婢侀幏鐑芥懚鏉炴澘宕昘閺夌偞娼欑敮顐f叏鐎h埖瀚归柨鐕傛嫹1闁跨噦鎷�7 */
signed int gyro_y_adc; /* 闂傚嫷婢侀幏鐑芥懚鏉炴澘宕昚閺夌偞娼欑敮顐f叏鐎h埖瀚归柨鐕傛嫹1闁跨噦鎷�7 */
signed int gyro_z_adc; /* 闂傚嫷婢侀幏鐑芥懚鏉炴澘宕昛閺夌偞娼欑敮顐f叏鐎h埖瀚归柨鐕傛嫹1闁跨噦鎷�7 */
signed int accel_x_adc; /* 闁告梻濯撮幏鐑芥晸閽樺顔婇悹渚囨憮閺夌偞娼欑敮顐f叏鐎h埖瀚归柨鐕傛嫹1闁跨噦鎷�7 */
signed int accel_y_adc; /* 闁告梻濯撮幏鐑芥晸閽樺顔婇悹渚囨憰閺夌偞娼欑敮顐f叏鐎h埖瀚归柨鐕傛嫹1闁跨噦鎷�7 */
signed int accel_z_adc; /* 闁告梻濯撮幏鐑芥晸閽樺顔婇悹渚囨憱閺夌偞娼欑敮顐f叏鐎h埖瀚归柨鐕傛嫹1闁跨噦鎷�7 */
signed int temp_adc; /* 婵炴挴鏅涚€规娊宕㈤悢濂夋綏闁稿⿵鎷�1闁跨噦鎷�7 */
/* 濞戞挸顑夊浼村及椤栨繍鍚€缂佺姵顨呯欢閬嶅礆閹殿喗鐣遍悗鍦仱濡绢垶宕愮涵椋庣闁圭鏅涢妵锟�100闁稿⿵鎷�1闁跨噦鎷�7 */
signed int gyro_x_act; /* 闂傚嫷婢侀幏鐑芥懚鏉炴澘宕昘閺夌偞娼欓悿鍕⒔閸滃啯瀚归柨鐕傛嫹1闁跨噦鎷�7 */
signed int gyro_y_act; /* 闂傚嫷婢侀幏鐑芥懚鏉炴澘宕昚閺夌偞娼欓悿鍕⒔閸滃啯瀚归柨鐕傛嫹1闁跨噦鎷�7 */
signed int gyro_z_act; /* 闂傚嫷婢侀幏鐑芥懚鏉炴澘宕昛閺夌偞娼欓悿鍕⒔閸滃啯瀚归柨鐕傛嫹1闁跨噦鎷�7 */
signed int accel_x_act; /* 闁告梻濯撮幏鐑芥晸閽樺顔婇悹渚囨憮閺夌偞娼欓悿鍕⒔閸滃啯瀚归柨鐕傛嫹1闁跨噦鎷�7 */
signed int accel_y_act; /* 闁告梻濯撮幏鐑芥晸閽樺顔婇悹渚囨憰閺夌偞娼欓悿鍕⒔閸滃啯瀚归柨鐕傛嫹1闁跨噦鎷�7 */
signed int accel_z_act; /* 闁告梻濯撮幏鐑芥晸閽樺顔婇悹渚囨憱閺夌偞娼欓悿鍕⒔閸滃啯瀚归柨鐕傛嫹1闁跨噦鎷�7 */
signed int temp_act; /* 婵炴挴鏅涚€瑰磭鈧湱鍋ゅ顖炲磹閿燂拷1闁跨噦鎷�7 */
};
extern struct icm20608_dev_struc icm20608_dev; /* icm20608閻犱焦鍎抽ˇ锟� */
void icm20608_init(void);
unsigned char icm20608_read_reg(unsigned char reg_address);/*閺夆晜绋栭、鎴犳嫚鐠囪尙妲戦悗娑櫭▍鎺楀极閻楀牆绁�*/
void icm20608_write_reg(unsigned char reg_address,unsigned char reg_in_data);/*閺夆晜绋栭、鎴﹀礃濞嗗繒妲戦悗娑櫭▍鎺楀极閻楀牆绁�*/
void icm20608_read_more(unsigned char reg,unsigned char *buf,unsigned char len);//閻犲洩顕чˇ鎸庣▔椤忓嫮妲戦悗娑櫭▍鎺楀磹閿燂拷
/*闂勨偓閾昏桨鍗庣拋锛勭暬闂団偓鐟曚胶娈戦崐锟�*/
float icm20608_gyro_scaleget(void);
/*閸旂娀鈧喎瀹崇拋陇顓哥粻妤呮付鐟曚胶娈戦崐锟�*/
unsigned short icm20608_accel_scaleget(void);
void icm20608_get_data(void);
#endif
主函数:
#include "main.h"
#include "dsp_clk.h"
#include "dsp_led.h"
#include "dsp_delay.h"
#include "beep.h"
#include "dsp_key.h"
#include "dsp_int.h"
#include "dsp_exti.h"
#include "dsp_epit.h"
#include "dsp_uart.h"
#include "stdio.h"
#include "dsp_lcd.h"
#include "dsp_lcdapi.h"
#include "dsp_rtc.h"
#include "dsp_i2c.h"
#include "dsp_ap3216c.h"
#include "dsp_spi.h"
#include "dsp_icm20608.h"
void imx6ul_hardfpu_enable(void)//使能浮点数运算
{
uint32_t cpacr;
uint32_t fpexc;
/* 使能NEON和FPU */
cpacr = __get_CPACR();
cpacr = (cpacr & ~(CPACR_ASEDIS_Msk | CPACR_D32DIS_Msk))
| (3UL << CPACR_cp10_Pos) | (3UL << CPACR_cp11_Pos);
__set_CPACR(cpacr);
fpexc = __get_FPEXC();
fpexc |= 0x40000000UL;
__set_FPEXC(fpexc);
}
void integer_display(unsigned short x, unsigned short y, unsigned char size, signed int num)//重新构建显示函数
{
char buf[200];
lcd_fill(x, y, x + 50, y + size, tftlcd_dev.backcolor);
memset(buf, 0, sizeof(buf));
if(num < 0)
sprintf(buf, "-%d", -num);
else
sprintf(buf, "%d", num);
lcd_show_string(x, y, 50, size, size, buf);
}
void decimals_display(unsigned short x, unsigned short y, unsigned char size, signed int num)//将整数结果转化为真实的数据
{
signed int integ; /* 整数部分 */
signed int fract; /* 小数部分 */
signed int uncomptemp = num;
char buf[200];
if(num < 0)
uncomptemp = -uncomptemp;
integ = uncomptemp / 100;
fract = uncomptemp % 100;
memset(buf, 0, sizeof(buf));
if(num < 0)
sprintf(buf, "-%d.%d", integ, fract);
else
sprintf(buf, "%d.%d", integ, fract);
lcd_fill(x, y, x + 60, y + size, tftlcd_dev.backcolor);
lcd_show_string(x, y, 60, size, size, buf);
}
int main(void)
{
// int b=0;
// unsigned short ir,ps,als;
unsigned char kkkk=0;
// struct rtc_datetime rtc_now_time;
// char buf[160]={};
imx6ul_hardfpu_enable();//打开浮点运算
int_init();//中断初始化
imx6u_clkinit();//时钟初始化
key_init();//按键初始化
clk_enable();//时钟初始化
uart_init();//串口初始化
beep_init();//凤鸣器初始化
led_init();//led初始化
lcd_init();//LCD读ID号
rtc_init();//RTC初始化
ap3216c_init();//传感器初始化
icm20608_init();//加速度计 陀螺仪等传感器初始化
tftlcd_dev.forecolor = LCD_RED;
tftlcd_dev.backcolor = LCD_WHITE;
// unsigned char *b,*c,*f;
// unsigned short *a;
// lcd_show_string(10,40,260,32,32,(char *)"Fucking high");
lcd_show_string(50, 130, 200, 16, 16, (char*)"accel x:");
lcd_show_string(50, 150, 200, 16, 16, (char*)"accel y:");
lcd_show_string(50, 170, 200, 16, 16, (char*)"accel z:");
lcd_show_string(50, 190, 200, 16, 16, (char*)"gyro x:");
lcd_show_string(50, 210, 200, 16, 16, (char*)"gyro y:");
lcd_show_string(50, 230, 200, 16, 16, (char*)"gyro z:");
lcd_show_string(50, 250, 200, 16, 16, (char*)"temp :");
lcd_show_string(50 + 181, 130, 200, 16, 16, (char*)"g");
lcd_show_string(50 + 181, 150, 200, 16, 16, (char*)"g");
lcd_show_string(50 + 181, 170, 200, 16, 16, (char*)"g");
lcd_show_string(50 + 181, 190, 200, 16, 16, (char*)"o/s");
lcd_show_string(50 + 181, 210, 200, 16, 16, (char*)"o/s");
lcd_show_string(50 + 181, 230, 200, 16, 16, (char*)"o/s");
lcd_show_string(50 + 181, 250, 200, 16, 16, (char*)"C");
while(1)
{
icm20608_get_data();
integer_display(50 + 70, 130, 16, icm20608_dev.accel_x_adc);
integer_display(50 + 70, 150, 16, icm20608_dev.accel_y_adc);
integer_display(50 + 70, 170, 16, icm20608_dev.accel_z_adc);
integer_display(50 + 70, 190, 16, icm20608_dev.gyro_x_adc);
integer_display(50 + 70, 210, 16, icm20608_dev.gyro_y_adc);
integer_display(50 + 70, 230, 16, icm20608_dev.gyro_z_adc);
integer_display(50 + 70, 250, 16, icm20608_dev.temp_adc);
decimals_display(50 + 70 + 50, 130, 16, icm20608_dev.accel_x_act);
decimals_display(50 + 70 + 50, 150, 16, icm20608_dev.accel_y_act);
decimals_display(50 + 70 + 50, 170, 16, icm20608_dev.accel_z_act);
decimals_display(50 + 70 + 50, 190, 16, icm20608_dev.gyro_x_act);
decimals_display(50 + 70 + 50, 210, 16, icm20608_dev.gyro_y_act);
decimals_display(50 + 70 + 50, 230, 16, icm20608_dev.gyro_z_act);
decimals_display(50 + 70 + 50, 250, 16, icm20608_dev.temp_act);
// unsigned char vallll;
// vallll = icm20608_read_reg(ICM20_WHO_AM_I);
// printf("ID:%x\r\n",vallll);
// ap3216c_redata(&ir,&ps,&als);
// lcd_shownum(200, 160, ir, 5, 32);
// lcd_shownum(200, 200, ps, 5, 32);
// lcd_shownum(200, 240, als, 5, 32);
// printf("ir = %d ps = %d als = %d \r\n",ir,ps,als);
// tftlcd_dev.forecolor = LCD_RED;
// rtc_out_register(&rtc_now_time);
// sprintf(buf,"%d.%d.%d-%d:%d:%d\r\n",rtc_now_time.year,rtc_now_time.month,
// rtc_now_time.day,rtc_now_time.hour,rtc_now_time.minute,rtc_now_time.second);
// lcd_show_string(70,70,240,32,32,(char *)buf);
led_mode(kkkk);
delay(1000);
kkkk = !kkkk;
}
return 0;
}
实现:
1.小tip
①#define IMC20608_CSN(n) (n ? gpio_write(GPIO1,20,1):gpio_write(GPIO1,20,0))
(n ? gpio_write(GPIO1,20,1):gpio_write(GPIO1,20,0))是3目运算,条件? 表达式1 : 表达式2,条件为真,执行表达式1,否则执行表达式2。因此当n=1,IMC20608_CSN(1)就相当于执行了 gpio_write(GPIO1,20,1),后面同理,利用宏定义来这样实现片选,很新颖。
②`
/*读多个寄存器值*/
void icm20608_read_more(unsigned char reg,unsigned char *buf,unsigned char len)
{
unsigned int i=0;
reg |=0x80;//设置为读模式
IMC20608_CSN(0);//使能
spi_read_and_write_byte(ECSPI3,reg);//先写入寄存器地址
for(i=0;i<len;i++)
{
buf[i]=spi_read_and_write_byte(ECSPI3,0xff);//??
}
IMC20608_CSN(1);//关闭使能
}
在 for 循环中,通过不断调用 spi_read_and_write_byte(ECSPI3, 0xff) 来连续读取数据。在 SPI 通信中,主设备发送什么数据并不影响从设备返回数据的过程,这里发送 0xff 通常是一种占位操作,目的是触发从设备在每个时钟周期返回数据。每调用一次该函数,从设备就会根据当前内部寄存器地址指针的位置返回一个字节的数据,同时地址指针自动指向下一个寄存器地址(这是由从设备内部的硬件机制实现的)。通过循环多次调用,就可以连续读取多个寄存器的值,并将它们存储到 buf 数组中。