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是通过在数据中发送从机的地址,选择从机设备。相同点:①都是串行通信,数据按位传输,②都是主从架构,一个主设备作为控制中心,多个从设备响应并进行数据的传输。
SPISPI通过串行时钟极性(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;//清0base->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));//清0base->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);//陀螺仪量程2000icm20608_write_reg(ICM20_ACCEL_CONFIG,0X18);//加速度16icm20608_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 数组中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/66545.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【从零开始入门unity游戏开发之——unity篇04】unity6基础入门 —— 新建项目模板的选择(渲染管线相关的知识点)

文章目录 前言一、渲染管线相关知识1、什么是渲染管线&#xff08;Render Pipeline&#xff09;&#xff1f;2、渲染管线的历史背景3、什么是 Scriptable Render Pipeline&#xff08;SRP&#xff09;&#xff1f;4、Unity三种渲染管线4.1 **内置渲染管线&#xff08;Built-in …

Nacos server 2.4.0 版本已知问题和 Bug 汇总

Nacos server 2.4.0 版本已知问题和 Bug 汇总 核心功能问题 集群模式下的数据一致性问题 在特定条件下&#xff0c;可能出现节点间数据同步延迟某些情况下会出现脑裂现象Issue #9876: 数据同步时可能出现死锁 内存泄漏问题 长时间运行后可能出现内存泄漏当配置变更频繁时&…

AI也会犯错

一、缘起 1.1 问题的发现 AI模型在处理数值比较问题时&#xff0c;出现了一个有趣的现象&#xff1a;当被问到“9.9”和“9.11”哪个更大时&#xff0c;一些AI模型给出了错误的答案&#xff0c;认为“9.9”大于“9.11”。这一问题最初是由 Riley Goodside 发现的&#xff0c;…

Telnet工具的使用

Mac 下载安装&#xff0c;双击打开Windows 默认自带&#xff0c;但需要开启使用&#xff0c;控制面板->启用或关闭windows功能->Telnet客户端 管理员身份启动终端&#xff0c;输入telnet。远程连接 telnet ip 端口号 #看到输出后再回车一次调用服务 首先明确项目中有哪些…

Python的Matplotlib库应用(超详细教程)

目录 一、环境搭建 1.1 配置matplotlib库 1.2 配置seaborn库 1.3 配置Skimage库 二、二维图像 2.1 曲线&#xff08;直线&#xff09;可视化 2.2 曲线&#xff08;虚线&#xff09;可视化 2.3 直方图 2.4 阶梯图 三、三维图像 3.1 3D曲面图 3.2 3D散点图 3.3 3D散…

一个个顺序挨着来 - 责任链模式(Chain of Responsibility Pattern)

责任链模式&#xff08;Chain of Responsibility Pattern&#xff09; 责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;概述责任链结构图责任链模式概述责任链模式涉及的角色 talk is c…

Laravel 新 WebSocket 服务 Reverb 使用指南

旧篇 > Laravel/Lumen 中使用 Echo Socket.IO-Client 实现网页即时通讯广播 https://blog.csdn.net/maxsky/article/details/130394420 已过时 与时俱进&#xff0c;Laravel 官方在 2024 年 7 月发布了 laravel/reverb 包的正式版&#xff0c;因为之前使用的 laravel-echo-…

网工考试下午题目笔记

1、在防火墙设备中&#xff0c;配置双出口链路有提高总带宽、链路负载均衡、提高可靠性的作用&#xff0c;通过配置链路聚合提高总带宽&#xff0c;通过配置策略路由提高链路负载均衡 防火墙工作模式有路由模式(防火墙接口配有IP地址)、透明模式(防火墙相当于不存在)、混合模式…

WEB攻防-通用漏洞_文件上传_黑白盒审计流程

目录 前置知识点 Finecms-CMS文件上传 ​编辑 Cuppa-Cms文件上传 Metinfo-CMS 文件上传 前置知识点 思路&#xff1a; 黑盒就是寻找一切存在文件上传的功能应用 1 、个人用户中心是否存在文件上传功能 2 、后台管理系统是否存在文件上传功能 3 、字典目录扫描探针文件上传构…

Agentic RAG 解释

RAG&#xff08;检索增强生成&#xff09;通过提供来自外部知识源的相关背景来帮助提高 LLM 答案的准确性和可靠性。 Agentic RAG 是高级 RAG 版本&#xff0c;它使用 AI 代理来更加自主地行动。 Agentic RAG 执行以下操作 查询理解、分解和重写检索策略选择知识库管理结果综…

apex安装

安装过程复杂曲折&#xff0c;网上说的很多办法&#xff0c;貌似成功了&#xff0c;实际还是没起作用。 先说成功过程&#xff0c;执行下面命令&#xff0c;安装成功&#xff08;当然&#xff0c;前提是你要先配置好编译环境&#xff09;&#xff1a; &#xff08;我的环境&a…

shell-条件判断

目录 一、条件判断 1.按照文件类型进行判断 2.按照文件权限进行判断 3.两个文件之间进行比较 4.两个整数之间进行比较 5.字符串的判断 6.多重条件判断 二、if条件判断 1.单分支if条件语句 2.双分支if条件语句 &#xff08;1&#xff09;判断某文件是否存在 &#x…

基于FPGA的出租车里程时间计费器

基于FPGA的出租车里程时间计费器 功能描述一、系统框图二、verilog代码里程增加模块时间增加模块计算价格模块上板视频演示 总结 功能描述 &#xff08;1&#xff09;&#xff1b;里程计费功能&#xff1a;3公里以内起步价8元&#xff0c;超过3公里后每公里2元&#xff0c;其中…

将数组转换为laravel中的对象

将数组转换为laravel中的对象 在Laravel中&#xff0c;可以通过使用集合&#xff08;Collection&#xff09;来将数组转换为对象。集合是Laravel提供的一个强大的工具&#xff0c;用于处理数组数据。 将数组转换为Laravel中的对象的步骤如下&#xff1a; 首先&#xff0c;确…

jdk8升级JDK21(Springboot2.7.18升级Springboot3.4.0)

目录 背景&#xff1a; 一、maven升级 二、代码改造 2.1 javax替换为jakarta 2.2 swagger2升级swagger3相关更新 2.2.1 新增SpringDocConfig配置类 2.2.2 全局代码更新 2.2.3 全局代码替换&#xff08;普通正则替换&#xff09; 2.3 Mybatis Plus升级 2.4 logback.xm…

AI赋能跨境电商:魔珐科技3D数字人破解出海痛点

跨境出海进入狂飙时代&#xff0c;AI应用正在深度渗透并重塑着跨境电商产业链的每一个环节&#xff0c;迎来了发展的高光时刻。生成式AI时代的大幕拉开&#xff0c;AI工具快速迭代&#xff0c;为跨境电商行业的突破与飞跃带来了无限可能性。 由于跨境电商业务自身特性鲜明&…

【HarmonyOS NEXT】鸿蒙应用实现屏幕录制详解和源码

【HarmonyOS NEXT】鸿蒙应用实现屏幕录制详解和源码 一、前言 官方文档关于屏幕录制的API和示例介绍获取简单和突兀。使用起来会让上手程度变高。所以特意开篇文章&#xff0c;讲解屏幕录制的使用。官方文档参见&#xff1a;使用AVScreenCaptureRecorder录屏写文件(ArkTS) 二…

Ubuntu挂载云盘操作步骤

1. 查看磁盘分区情况 使用 fdisk -l 命令查看当前系统中所有磁盘的分区情况&#xff0c;找到需要挂载的云盘设备&#xff0c;例如/dev/vdc。 2. 创建新分区 使用 fdisk /dev/vdc 命令对云盘进行分区操作&#xff1a; 输入n创建新分区。 输入p选择创建主分区。 输入1指定分区…

stm32u5串口点灯

通过对单个字符输入的拼接暂存&#xff0c;实现对字符串的比较控制灯的亮灭 char buf[32];char temp[32];while (1){printf("start\n\r");memset(temp,0, sizeof(temp));memset(buf,0, sizeof(buf));while(temp[0] !\r){memset(temp,0, sizeof(temp));HAL_UART_Rece…

PHP 5 6 7 8 9 各重要版本开发特性和选择简要说明

PHP开发&#xff0c;所用版本的选型 PHP5.4是最后一个支持纯正32位操作系统的版本&#xff0c;在Winxp下仍可使用。 PHP5.6是php5.x的最后一个稳定版本&#xff0c;时至今天&#xff0c;仍有很多用户网站系统在使用&#xff0c;网上仍有很多学习资料是基于这个版本&#xff0c;…