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;//清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 数组中。
相关文章:
Linux-Ubuntu之SPI串行通信陀螺仪和加速度计
Linux-Ubuntu之SPI串口通信陀螺仪和加速度计 一,SPI通信原理二,ICM-20608六轴传感器控制三,代码1.小tip 一,SPI通信原理 SPI:串行全双工通信,最高能达到百MHZ,通常一个主设备跟多个从设备&…...
【C++/控制台】2048小游戏
源代码: #include <iostream> #include <windows.h> #include <stdio.h> #include <math.h> #include <stdlib.h> #include <conio.h> #include <time.h>// #define KEY_DOWN(VK_NONAME) ((GetAsyncKeyState(VK_NONAME)…...
github gitbook写书
github创建新的仓库 在仓库中添加目录 ‘SUMMARY.md # Summary * [简介](README.md)gitbook 新建一个site https://www.gitbook.com/ 注册账号 取名字 一路 next,注意选免费版 最后 gitbook同步到github 你在主页可以看到 刚刚的test网站 点击右上角圈出来…...
鸿蒙中调整应用内文字大小
1、ui Stack() {Row() {ForEach([1, 2, 3, 4], (item: number) > {Text().width(3).height(20).backgroundColor(Color.Black).margin(item 2 ? { left: 8 } : item 3 ? { left: 7 } : { left: 0 })})}.width(97%).justifyContent(FlexAlign.SpaceBetween).padding({ ri…...
欧拉公式和傅里叶变换
注:英文引文机翻,未校。 中文引文未整理去重,如有异常,请看原文。 Euler’s Formula and Fourier Transform Posted byczxttkl October 7, 2018 Euler’s formula states that e i x cos x i sin x e^{ix} \cos{x} i …...
【C++经典例题】求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句
💓 博客主页:倔强的石头的CSDN主页 📝Gitee主页:倔强的石头的gitee主页 ⏩ 文章专栏: 期待您的关注 题目描述: 原题链接: 求123...n_牛客题霸_牛客网 (nowcoder.com) 解题思路: …...
Robot---奇思妙想轮足机器人
1 背景 传统机器人有足式、轮式、履带式三种移动方式,每种移动方式都有各自的优缺点。轮式机器人依靠车轮在地面上移动,能源利用率高、移动速度快,但是仅以轮子与地面接触,缺乏越障能力和对复杂地形的适应能力,尤其面对…...
升级 Spring Boot 3 配置讲解 —— 如何处理文件上传下载?
学会这款 🔥全新设计的 Java 脚手架 ,从此面试不再怕! 1. 环境准备 在开始之前,确保你已经具备以下环境: JDK 17 或更高版本(Spring Boot 3 要求的最低 JDK 版本)Maven 或 Gradle 构建工具Spr…...
(四)结合代码初步理解帧缓存(Frame Buffer)概念
帧缓存(Framebuffer)是图形渲染管线中的一个非常重要的概念,它用于存储渲染过程中产生的像素数据,并最终输出到显示器上。简单来说,帧缓存就是计算机图形中的“临时画布”,它储存渲染操作生成的图像数据&am…...
WebRTC 在视频联网平台中的应用:开启实时通信新篇章
在当今这个以数字化为显著特征的时代浪潮之下,实时通信已然稳稳扎根于人们生活与工作的方方面面,成为了其中不可或缺的关键一环。回首日常生活,远程办公场景中的视频会议让分散各地的团队成员能够跨越地理距离的鸿沟,齐聚一堂共商…...
Python文件操作
文件的编码 文件编码 思考:计算机只能识别:0和1,那么我们丰富的文本文件是如何被计算机识别,并存储在硬盘中呢? 答案:使用编码技术(密码本)将内容翻译成0和1存入。 编码技术即&am…...
【渗透测试术语总结】
Top 渗透测试常用专业术语 相信大家和我一样,搞不清这些专业名词的区别,所以我来整理一下。 1. POC、EXP、Payload与Shellcode POC:全称 Proof of Concept ,中文 概念验证 ,常指一段漏洞证明的代码。 EXP…...
利用ArcGIS快速准确地统计出地块的现状容积率
研究目的 根据建筑.dwg、建筑.dwg Annotation、建筑.dwg Polygon,地籍边界.shp等数据,利用GIS快速准确地统计出地块的现状容积率。 研究思路 加载数据图层:建筑.dwg Polygon、建筑.dwg Annotation,使用空间连接功能把建筑层数数…...
Linux:守护进程
一、套路 直接来,不铺垫了; #include<iostream> #include<string> #include<cstdlib> #include<unistd.h> #include<unistd.h> #include<sys/types.h> #include<sys/stat.h> #include<funtl.h> const …...
《Spring Framework实战》3:概览
欢迎观看《Spring Framework实战》视频教程 Spring Framework 为基于现代 Java 的企业应用程序提供了全面的编程和配置模型 - 在任何类型的部署平台上。 Spring 的一个关键要素是应用程序级别的基础设施支持:Spring 专注于企业应用程序的 “管道”,以便…...
【云商城】高性能门户网构建
第3章 高性能门户网构建 网站门户就是首页 1.OpenResty 百万并发站点架构 1).OpenResty 特性介绍 2).搭建OpenResty 3).Web站点动静分离方案剖析 2.Lua语法学习 1).Lua基本语法 3.多级缓存架构实战 1).多级缓存架构分析 用户请求网站,最开始…...
IvorySQL 升级指南:从 3.x 到 4.0 的平滑过渡
日前,IvorySQL 4.0 重磅发布,全面支持 PostgreSQL 17,并且增强了对 Oracle 的兼容性。关于 IvorySQL 4.0 的介绍,各位小伙伴可以通过这篇文章回顾:IvorySQL 4.0 发布:全面支持 PostgreSQL 17. 在 IvorySQL…...
GESP202312 四级【小杨的字典】题解(AC)
》》》点我查看「视频」详解》》》 [GESP202312 四级] 小杨的字典 题目描述 在遥远的星球,有两个国家 A 国和 B 国,他们使用着不同的语言:A 语言和 B 语言。小杨是 B 国的翻译官,他的工作是将 A 语言的文章翻译成 B 语言的文章…...
数据库_解决SQL Server数据库log日志过大,清理日志文件方法
SQL Server数据库日志文件过大的原因主要有几个方面: 事务日志记录了所有对数据库进行修改的操作,如插入、更新和删除,这些操作会不断增加日志文件的大小。 长时间运行且未正确结束的事务会持续占用事务日志中的空间,导致日志文…...
Java 的单例模式详解及优化
💖 欢迎来到我的博客! 非常高兴能在这里与您相遇。在这里,您不仅能获得有趣的技术分享,还能感受到轻松愉快的氛围。无论您是编程新手,还是资深开发者,都能在这里找到属于您的知识宝藏,学习和成长…...
关于 webservice 日志中 源IP是node IP的问题,是否能解决换成 真实的客户端IP呢
本篇目录 1. 问题背景2. 部署gitlab 17.52.1 添加repo源2.2 添加repo源 下载17.5.0的charts包2.3 修改values文件2.3.1 hosts修改如下2.3.2 appConfig修改如下2.3.3 gitlab下的sidekiq配置2.3.4 certmanager修改如下2.3.5 nginx-ingress修改如下2.3.6 <可选> prometheus修…...
[python3]xlrd不支持Excel xlsx文件类型
https://xlrd.readthedocs.io/en/latest/ xlrd is a library for reading data and formatting information from Excel files in the historical .xls format. 解决办法:指定支持的版本1.2.0,pip3 install xlrd1.20 pip3 install xlrd1.2.0 Looking …...
React中createRoot函数原理解读——Element对象与Fiber对象、FiberRootNode与HostRootNode
【2024最新版】React18 核心源码分析教程(全61集) Element对象与Fiber对象 在 React 中,Element 对象 和 Fiber 对象 是核心概念,用于实现 React 的高效渲染和更新机制。以下是它们的详细解读: 1. Element 对象 定…...
【网络协议】动态路由协议
前言 本文将概述动态路由协议,定义其概念,并了解其与静态路由的区别。同时将讨论动态路由协议相较于静态路由的优势,学习动态路由协议的不同类别以及无类别(classless)和有类别(classful)的特性…...
DevOps:CI、CD、CB、CT、CD
目录 一、软件开发流程演化快速回顾 (一)瀑布模型 (二)原型模型 (三)螺旋模型 (四)增量模型 (五)敏捷开发 (六)DevOps 二、走…...
网络安全 | WAF防护开通流程与技术原理详解
关注:CodingTechWork 引言 随着互联网安全形势的日益严峻,Web应用防火墙(WAF, Web Application Firewall)逐渐成为网站和应用的标准防护措施。WAF能够有效识别和防止如SQL注入、跨站脚本攻击(XSS)、恶意流…...
【我的 PWN 学习手札】IO_FILE 之 FSOP
FSOP:File Stream Oriented Programming 通过劫持 _IO_list_all 指向伪造的 _IO_FILE_plus,进而调用fake IO_FILE 结构体对象中被伪造的vtable指向的恶意函数。 目录 前言 一、glibc-exit函数浅析 二、FSOP 三、Largebin attack FSOP (…...
Spring——自动装配
假设一个场景: 一个人(Person)有一条狗(Dog)和一只猫(Cat),狗和猫都会叫,狗叫是“汪汪”,猫叫是“喵喵”,同时人还有一个自己的名字。 将上述场景 抽象出三个实体类&…...
C语言——文件IO 【文件IO和标准IO区别,操作文件IO】open,write,read,dup2,access,stat
1.思维导图 2.练习 1:使用C语言编写一个简易的界面,界面如下 1:标准输出流 2:标准错误流 3:文件流 要求:按1的时候,通过printf输出数据,按2的时候,通过p…...
人工智能知识分享第九天-机器学习_集成学习
集成学习 概念 集成学习是机器学习中的一种思想,它通过多个模型的组合形成一个精度更高的模型,参与组合的模型称为弱学习器(基学习器)。训练时,使用训练集依次训练出这些弱学习器,对未知的样本进行预测时…...
腾讯云AI代码助手编程挑战赛-武器大师
作品简介 对话过程能够介绍二战 各种武器 冷战 武器 现代的 各种武器装备,陆海空三军都知道。 技术架构 使用全后端分离的架构,前端使用Vue脚手架,腾讯云修改样式css 开发环境、开发流程 系统:win11 开发工具:VS…...
Python机器学习笔记(十八、交互特征与多项式特征)
添加原始数据的交互特征(interaction feature)和多项式特征(polynomial feature)可以丰富特征表示,特别是对于线性模型。这种特征工程可以用统计建模和许多实际的机器学习应用中。 上一次学习:线性模型对w…...
java_深入理解main方法
深入理解main方法 在 main()方法中,我们可以直接调用 main 方法所在类的静态方法或静态属性。但是,不能直接访问该类中的非静态成员,必须创建该类的一个实例对象后,才能通过这个对象去访问类中的非静态成员,[举例说明]…...
NLP中常见的分词算法(BPE、WordPiece、Unigram、SentencePiece)
文章目录 一、基本概念二、传统分词方法2.1 古典分词方法2.2 拆分为单个字符 三、基于子词的分词方法(Subword Tokenization)3.1 主要思想3.2 主流的 Subword 算法3.3 Subword 与 传统分词方法的比较 四、Byte Pair Encoding (BPE)4.1 主要思想4.2 算法过…...
HTTP/HTTPS ②-Cookie || Session || HTTP报头
这里是Themberfue 上篇文章介绍了HTTP报头的首行信息 本篇我们将更进一步讲解HTTP报头键值对的含义~~~ ❤️❤️❤️❤️ 报头Header ✨再上一篇的学习中,我们了解了HTTP的报头主要是通过键值对的结构存储和表达信息的;我们已经了解了首行的HTTP方法和UR…...
前端 动图方案
1、vue3lottie 解析使用Bodymovin导出为json格式的Adobe After Effects动画 vue3lottie的使用神器:vue3-lottie (electron也适用)-CSDN博客 2、MP4文件 //template部分 <video class"header-bg" src"../../assets/images/screen/layout/heade…...
C#语言的字符串处理
C#语言的字符串处理 引言 在现代编程中,字符串处理是一项重要的技能,几乎在所有编程语言中都有应用。C#语言作为一种强类型的、面向对象的编程语言,提供了丰富的字符串处理功能。这使得开发人员能够方便地进行文本操作,比如字符…...
【shell编程】报错信息:bash: bad file descriptor(包含6种解决方法)
大家好,我是摇光~ 在运行 Shell 脚本时,遇到 bash: bad file descriptor 错误通常意味着脚本尝试对一个无效或不可用的文件描述符(file descriptor)执行了读写操作。 以下是一些可能导致这个问题的原因、详细案例以及相应的解决…...
vscode 配置c/c++环境 中文乱码
D:\MIscrobingDownload\mingw64\binmingw配置到环境变量中 测试一下,按winr输入cmd打开终端 gcc -v g -v安装插件 一 二 run code 因为run code 插件配置实质上是用它提供的指令进行编译执行,因此无法直接使用断点调试功能,需要对配置进行…...
leetcode 面试经典 150 题:两数之和
链接两数之和题序号1题型数组解题方法1. 哈希表,2. 暴力法难度简单熟练度✅✅✅✅✅ 题目 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。 你可以假设每种输…...
【Unity报错】error Cs0103: The name ‘keyCode‘ does not exist in the current context
报错提示: 解决方法: KeyCode K大写...
家用万兆网络实践:紧凑型家用服务器静音化改造(二)
大家好,这篇文章我们继续分享家里网络设备的万兆升级和静音改造经验,希望对有类似需求的朋友有所帮助。 写在前面 在上一篇《家用网络升级实践:低成本实现局部万兆(一)》中,我们留下了一些待解决的问题。…...
“AI智能实训系统:让学习更高效、更轻松!
大家好,作为一名资深产品经理,今天我来跟大家聊聊一款备受瞩目的产品——AI智能实训系统。在这个人工智能技术飞速发展的时代,AI智能实训系统应运而生,为广大学习者提供了全新的学习体验。那么,这款产品究竟有哪些亮点…...
【Linux 之一 】Linux常用命令汇总
Linux常用命令 ./catcd 命令chmodclearcphistoryhtoplnmkdirmvpwdrmtailunamewcwhoami 我从2021年4月份开始才开始真正意义上接触Linux,最初学习时是一脸蒙圈,啥也不会,啥也不懂,做了很多乱七八糟,没有条理的笔记。不知…...
Git 从入门到精通
一、环境配置 下载地址:https://git-scm.com/downloads/ 二、用户配置 找到git bash git --version 查看当前版本 git config --global user.name szhipeng625 设置用户名 git config --global user.email szhipeng625gmail.com 设置邮箱 git config --global …...
【Uniapp-Vue3】创建自定义页面模板
大多数情况下我们都使用的是默认模板,但是默认模板是Vue2格式的,如果我们想要定义一个Vue3模板的页面就需要自定义。 一、我们先复制下面的模板代码(可根据自身需要进行修改): <template><view class"…...
Ansible之批量管理服务器
文章目录 背景第一步、安装第二步、配置免密登录2.1 生成密钥2.2 分发公钥2.3 测试无密连接 背景 Ansible是Python强大的服务器批量管理 第一步、安装 首先要拉取epel数据源,执行以下命令 yum -y install epel-release安装完毕如下所示。 使用 yum 命令安装 an…...
android compose 串口通信
1.添加依赖 implementation("io.github.xmaihh:serialport:2.1.1") 2.添加SerialHelper派生类 class SerialPortHelper(portName:String,baudRate:Int): SerialHelper(portName,baudRate) {var receivedDataBuffer mutableListOf<Byte>()override fun onDa…...
ios脚本巨魔商店多巴胺越狱基本操作教程
准备工作 确认设备兼容性:A9-A11(iPhone6s-X):iOS15.0-16.6.1;A12-A14(iPhoneXR-12PM):iOS15.0-16.5.1;A15-A16(iPhone13-…...
NLP项目实战——基于Bert模型的多情感评论分类(附数据集和源码)
在当今数字化的时代,分析用户评论中的情感倾向对于了解产品、服务的口碑等方面有着重要意义。而基于强大的预训练语言模型如 Bert 来进行评论情感分析,能够取得较好的效果。 在本次项目中,我们将展示如何利用 Python 语言结合transformers库&…...