C语言中的模式宏ACC_MODE文件访问控制以及O_ACCMODE

本文深入解析C语言中不常见的数组索引技巧,利用字符的ASCII码值进行复杂运算,展示了一种宏定义中字符串与数值运算相结合的高级应用实例。
#include
int main()
{
unsigned char result = 1["night"]*2["girls"]+4["allnight"];
char *of_you = "Though you was strong enough and seem never died";
printf("You got %s", result+of_you);
return 0;
}
1["night"]就是*("night"+1),也就是'i',ascii码为105
类似,2["multis"]是'l'(114)
4["allnight"]是'i'(105)
result=(105*114+105)%256=43
result+of_you=43+"Though you was strong enough and seem never died"
指向第43个字符

这是个比较令人郁闷的宏,我初一看曾质疑过C里面有这种写法么?呵呵,说实话还真有,C里面数组还真有这样的写法,只不过平时我们很少用过罢了。

回想一下,例如数组,a[b], 其中 a为基址, [] 里面的b为偏移量。数组里的元素就是靠 index=base + offset 来索引(基址与偏移量都是值,没有差异,所以位置可以互换, 而index为内存地址) 。 所以说上面的那种形式,是这个特例 第一个元素都是基址,而第二个元素都是用[]扩起 那么它就是偏移量。只是常量字符串它的值为他的首地址,地址也是一个值(c语言是只是传值) 。所以进一步推广 这里的a、b 可以是求值表达式  那么上述两个例子的行为就在情理之中了.
下面我再给出 linux/fs/namei.c 中的一个例子 :
#define ACC_MODE(x) ("\004\002\006\377"[(x)&O_ACCMODE])

#include "mpu6050.h" #include "delay.h" #include "sys.h" // MPU6050 I2C地址 #define MPU6050_ADDR 0xD0 // MPU6050寄存器地址 #define PWR_MGMT_1 0x6B #define SMPLRT_DIV 0x19 #define CONFIG 0x1A #define GYRO_CONFIG 0x1B #define ACCEL_CONFIG 0x1C #define INT_ENABLE 0x38 #define ACCEL_XOUT_H 0x3B #define GYRO_XOUT_H 0x43 // 加速度计和陀螺仪原始数据 short acc_x, acc_y, acc_z; short gyro_x, gyro_y, gyro_z; // 初始化MPU6050 u8 MPU6050_Init(void) { I2C_InitTypeDef I2C_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; // 使能I2C1和GPIO时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 配置I2C1的SCL和SDA引脚 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); // 配置I2C1 I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; I2C_InitStructure.I2C_OwnAddress1 = 0x00; I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_InitStructure.I2C_ClockSpeed = 400000; I2C_Init(I2C1, &I2C_InitStructure); I2C_Cmd(I2C1, ENABLE); // 复位MPU6050 MPU6050_Write_Byte(PWR_MGMT_1, 0x80); delay_ms(100); // 唤醒MPU6050并选择陀螺仪X轴作为时钟源 MPU6050_Write_Byte(PWR_MGMT_1, 0x01); delay_ms(100); // 设置采样率为1kHz MPU6050_Write_Byte(SMPLRT_DIV, 0x07); // 配置陀螺仪和加速度计的低通滤波器 MPU6050_Write_Byte(CONFIG, 0x06); // 配置陀螺仪量程为±2000°/s MPU6050_Write_Byte(GYRO_CONFIG, 0x00); // 配置加速度计量程为±2g MPU6050_Write_Byte(ACCEL_CONFIG, 0x00); // 启用中断 MPU6050_Write_Byte(INT_ENABLE, 0x01); // 检查MPU6050 ID if(MPU6050_Read_Byte(0x75) != 0x68) return 1; return 0; } // I2C写一个字节 void MPU6050_Write_Byte(u8 reg, u8 data) { while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)); I2C_GenerateSTART(I2C1, ENABLE); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2C1, MPU6050_ADDR, I2C_Direction_Transmitter); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); I2C_SendData(I2C1, reg); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); I2C_SendData(I2C1, data); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); I2C_GenerateSTOP(I2C1, ENABLE); } // I2C读一个字节 u8 MPU6050_Read_Byte(u8 reg) { u8 data; while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)); I2C_GenerateSTART(I2C1, ENABLE); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2C1, MPU6050_ADDR, I2C_Direction_Transmitter); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); I2C_SendData(I2C1, reg); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); I2C_GenerateSTART(I2C1, ENABLE); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2C1, MPU6050_ADDR, I2C_Direction_Receiver); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); I2C_AcknowledgeConfig(I2C1, DISABLE); I2C_GenerateSTOP(I2C1, ENABLE); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)); data = I2C_ReceiveData(I2C1); return data; } // I2C读多个字节 void MPU6050_Read_Len(u8 reg, u8 len, u8 *buf) { while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)); I2C_GenerateSTART(I2C1, ENABLE); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2C1, MPU6050_ADDR, I2C_Direction_Transmitter); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); I2C_SendData(I2C1, reg); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); I2C_GenerateSTART(I2C1, ENABLE); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2C1, MPU6050_ADDR, I2C_Direction_Receiver); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); for(u8 i = 0; i < len; i++) { if(i == len - 1) { I2C_AcknowledgeConfig(I2C1, DISABLE); I2C_GenerateSTOP(I2C1, ENABLE); } while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)); buf[i] = I2C_ReceiveData(I2C1); } } // 读取MPU6050数据 void MPU6050_GetData(void) { u8 buf[14]; MPU6050_Read_Len(ACCEL_XOUT_H, 14, buf); acc_x = ((u16)buf[0] << 8) | buf[1]; acc_y = ((u16)buf[2] << 8) | buf[3]; acc_z = ((u16)buf[4] << 8) | buf[5]; gyro_x = ((u16)buf[8] << 8) | buf[9]; gyro_y = ((u16)buf[10] << 8) | buf[11]; gyro_z = ((u16)buf[12] << 8) | buf[13]; } // 检测摇晃 u8 MPU6050_DetectShake(void) { static short last_acc_x = 0, last_acc_y = 0, last_acc_z = 0; short diff_x, diff_y, diff_z; u8 shake_intensity = 0; MPU6050_GetData(); diff_x = acc_x > last_acc_x ? acc_x - last_acc_x : last_acc_x - acc_x; diff_y = acc_y > last_acc_y ? acc_y - last_acc_y : last_acc_y - acc_y; diff_z = acc_z > last_acc_z ? acc_z - last_acc_z : last_acc_z - acc_z; // 计算摇晃强度 shake_intensity = (diff_x + diff_y + diff_z) / 1000; last_acc_x = acc_x; last_acc_y = acc_y; last_acc_z = acc_z; return shake_intensity; } // 检测深蹲 u8 MPU6050_DetectSquat(void) { static u8 squat_state = 0; static short last_acc_z = 0; static u32 squat_time = 0; MPU6050_GetData(); // 深蹲检测算法:检测加速度Z轴的变化 if(squat_state == 0) { // 初始状态,等待蹲下 if(acc_z < last_acc_z - 1000) { squat_state = 1; squat_time = 0; } } else if(squat_state == 1) { // 已蹲下,等待站起 if(acc_z > last_acc_z + 1000) { squat_state = 0; squat_time++; if(squat_time > 5) // 避免误触发 { squat_time = 0; return 1; // 检测到一次深蹲 } } } last_acc_z = acc_z; return 0; } 这是我的mpu6050代码,以下是我的报错信息:*** Using Compiler 'V5.06 update 5 (build 528)', folder: 'E:\app\ARM\ARMCC\Bin' Build target 'Target 1' compiling mpu6050.c... Hardwore\mpu6050.c(50): warning: #223-D: function "MPU6050_Write_Byte" declared implicitly MPU6050_Write_Byte(PWR_MGMT_1, 0x80); Hardwore\mpu6050.c(73): warning: #223-D: function "MPU6050_Read_Byte" declared implicitly if(MPU6050_Read_Byte(0x75) != 0x68) Hardwore\mpu6050.c(80): error: #159: declaration is incompatible with previous "MPU6050_Write_Byte" (declared at line 50) void MPU6050_Write_Byte(u8 reg, u8 data) Hardwore\mpu6050.c(100): error: #159: declaration is incompatible with previous "MPU6050_Read_Byte" (declared at line 73) u8 MPU6050_Read_Byte(u8 reg) Hardwore\mpu6050.c: 2 warnings, 2 errors compiling main.c... ".\Objects\Project.axf" - 2 Error(s), 2 Warning(s). Target not created. Build Time Elapsed: 00:00:01
最新发布
07-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值