工具/软件:Code Composer Studio
我正在处理一个项目、与 Max30101传感器通信以读取 SP02数据。 但使用示波器。 我意识到,在 I2CSEL 结束期间,写入数据中的1个字节丢失。 代码如下所示。
klib1.h 是 https://github.com/sparkfun/SparkFun_MAX3010x_Sensor_Library/blob/master/src/MAX30105.cpp 的修改版本。 例如 ,当我尝试“I2CSend (I2CDEVICE_ADDR,2,MAX30105_LED1_PULSEAMP,0x01);”时 ,我能够按预期打开红色 LED。 但情况并非总是如此。 大多数情况下、"MAX30105_LED1_PULSEAMP"将消失、因此红色 LED 不会亮起。
#include
#include
#include
#include
#include
#include "inc/hw_i2c.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"
#include "driverlib/i2c.h"
#include "driverlib/sysbt.h"
#driverlib/intrl.idu.ide"
#include "driverlib/u32ns/intrl.id_unt #include "driverlib.idr32";"drivers/u.idr32ns/intru.idrs/inu.rt.idr.idr.idr./u.idr./u.idr.idr.idr.idr.idr./u.idr.idr.idr./u.idr.idr.idr.idr./u.idr./u.idr.idr.idr./u.idr.idr./ 除以3个 cz 3个 clk 周期。
静态无符号长整型 WaitI2CDone (unsigned int long ulBase){
//等待直到传输完成
while (I2CMasterBusy (I2C0_BASE));
//返回 I2C 错误代码
返回 I2CMasterErr (I2C0_BASE);
}
//I2C 发送函数
//向指定的从设备发送 I2C 命令
//例如:I2CEND (LCD_SLAVE_ADDR、3、LCD_CMD、0x50、对比度);
void I2CSend (uint8_t slave_addr、uint8_t num_for_args、...)
{
uint8_t i = 0;
//告诉主模块何时将在总线上放置什么地址
//与从设备通信。
I2CMasterSlaveAddrSet (I2C0_BASE、SLAVE_addr、false);
//存储变量数量的参数列表
va_list vargs;
//将 va_list 指定为"open"和最后一个固定参数
//so vargs 知道从何处开始查找
va_start (vargs、num_of _args);
//将要发送的数据放入 FIFO 中
I2CMasterDataPut (I2C0_BASE、va_arg (vargs、uint32_t));
//如果只有一个参数,我们只需要使用
//单发送 I2C 函数
if (num_of _args == 1)
{
//从 MCU 发起数据发送
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_SINGLE_SEND);
//等待 MCU 完成传输。
while (I2CMasterBusy (I2C0_BASE));
//"close"变量参数列表
va_end (vargs);
}
//否则,我们开始在上传输多个字节
//I2C 总线
其他
{
//从 MCU 发起数据发送
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_SEND_START);
//等待 MCU 完成传输。
while (I2CMasterBusy (I2C0_BASE));
//send num_of _args-2数据片段、使用
///burse_send_contt 命令的 I2C 模块
for (i = 1;i <(num_of _args - 1);i++)
{
//将下一段数据放入 I2C FIFO 中
I2CMasterDataPut (I2C0_BASE、va_arg (vargs、uint32_t));
//发送刚刚放置到 FIFO 中的下一个数据
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_SEND_CONT);
//等待 MCU 完成传输。
while (I2CMasterBusy (I2C0_BASE));
}
//将最后一段数据放入 I2C FIFO 中
I2CMasterDataPut (I2C0_BASE、va_arg (vargs、uint32_t));
//发送刚刚放置到 FIFO 中的下一个数据
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_SEND_FINISH);
//等待 MCU 完成传输。
while (I2CMasterBusy (I2C0_BASE));
//"Close"变量 args 列表
va_end (vargs);
}
}
//I2C 接收功能
//读取从器件
上的指定寄存器 uint32_t I2CReceive(Uint32_t SLAVE_addr、uint8_t reg)
{
uint8_t data = 0;
int16_t i2c_err = I2C_MASTER_ERR_NONE;
//指定我们要向写入(寄存器地址)
//从器件
I2CMasterSlaveAddrSet (I2C0_BASE、SLAVE_addr、false);
//指定要读取的寄存器
I2CMasterDataPut (I2C0_BASE、reg);
//将控制字节和寄存器地址字节发送到从器件
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_SEND_START);
//等待 MCU 完成事务
while (I2CMasterBusy (I2C0_BASE));
//指定我们将从从从器件读取
I2CMasterSlaveAddrSet (I2C0_BASE、SLAVE_addr、TRUE);
//发送控制字节并从我们的寄存器中读取
//specified
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_SINGLE_Receive);
if (i2c_err!= WaitI2CDone (I2C0_BASE)){
数据= I2CMasterDataGet (I2C0_BASE);
UARTprintf ("数据中的读取错误:%x\n"、数据);
}
//等待 MCU 完成事务
while (I2CMasterBusy (I2C0_BASE));
//返回从指定寄存器提取的数据
返回 I2CMasterDataGet (I2C0_BASE);
}
void 位掩码(uint8_t reg、uint8_t mask、uint8_t sing)
{
//抓取当前寄存器上下文
uint8_t originalContents = I2Coriginive (I2CDEVICE_ADDR、reg);
//将部分
内容全部删除;更改 I2CDe2
和 I2ADDR | originale2 | origined 内容= originive.
void setFIFOAimage (uint8_t NumberOfSamples){
bitmask (MAX30105_FIFOCONFIG、MAX30105_SAMPLEAVG_MASK、NumberOfSamples);
}
void enableFIFORlover (void){
bitmask (MAX30105_FIFOCONFIG、MAX30105_MASK、NumberOfSamples);}void enableFIFORollover (void enover){void translover (void){void translover (void)}/ void translover (void translover){void translover (void)}){bit maged
(void)}
//请参阅数据表、第19页
的位掩码(MAX30105_MODECONFIG、MAX30105_MODE_MASK、MODE);
}
void setADCRange (uint8_t adcRange){
// adcRange:MAX30105_ADCRANGE_2048、_4096、_8192、_16105
bitCLA_MASK (MAX30105_ADCRANGE_2048)中的一个 adcRange);
}
void setSampleRate (uint8_t sampleRate){
// sampleRate:MAX30105_SAMPLERATE_50、_100、_200、_400、_800、 _1000、_1600、_3200
位掩码(MAX30105_PARTICLECONFIG、MAX30105_SAMPLEREATE_MASK、sampleRate);
}
void setPulseWidth (uint8_t pulsewidth){
// pulsewidth:MAX30105_pulsewidth_69的其中一个、_188、_215、_411
位掩码(MAX30105_PARTICLECONFIG、MAX30105_pulsewidth_MASK、 pulsewidth);
}
//注意:振幅值:0x00 = 0mA、0x7F = 25.4mA、0xFF = 50mA (典型值)
//请参阅数据表、第21页
void setPulseAmp 振
幅红色(uint8_t 振幅){I2CSend (I2CDEVICE_ADDR、2、MAx105_LED1_LEADDR 振幅)、void (uint2UCD3_demp)、void P30t_magpend_magmagse_se_magmagmagmagme_se_se_se_se_se_se_se_se_sei20uelt
);}
void setPulseAmplitudeProximity (uint8_t samplity){
i2CSend (I2CDEVICE_ADDR、2、MAX30105_LED_PROx_AMP、sampling);
}
void setProximityThreshold (uint8_t THRESB){
//设置将触发颗粒感应模式开始的 IR ADC 计数。
// THRESHMSB 只表示 ADC 计数的8个最高有效位。
//请参阅数据表第24页。
I2CSend (I2CDEVICE_ADDR、2、MAX30105_PROXINTTHRESH、THRESB);
}
//给定插槽编号为其分配一个东西
//设备为 SLOT_RED_LED 或 SLOT_RED_PULSE (接近)
//分配 SLOT_RED_LED 将脉冲 LED//A
RELEARD_PLETDIN?
void enableSlot (uint8_t slotNumber、uint8_t device){
switch (slotNumber){
情况(1):
位掩码(MAX30105_MULTILEDCONFIG1、MAX30105_SLOT1_MASK、器件);
中断;
情况(2):
位掩码(MAX30105_MULTILEDCONFIG1、MAX30105_SLOT2_MASK、器件<< 4);
中断;
情况(3):
位掩码(MAX30105_MULTILEDCONFIG2、MAX30105_SLOT3_MASK、器件);
中断;
情况(4):
位掩码(MAX30105_MULTILEDCONFIG2、MAX30105_SLOT4_MASK、器件<< 4);
中断;
默认值:
//不应该在这里!
break;
}
}
void clearFIFO (void){
I2CSend (I2CDEVICE_ADDR、2、MAX30105_FIFOWRITEPTR、0);
I2CSend (I2CDEVICE_ADDR、 2、MAX30105_FIFOOVERFLOW、0);
I2CSEND (I2CDEVICE_ADDR、2、 MAX30105_FIFOREADPTR、0);
}
void softReset (void){
bitmask (MAX30105_MODECONFIG、MAX30105_RESET_MASK、MAX30105_RESET);
while (1)
{
uint8_t 响应= I2CReceive (I2CDEVICE_ADDR、MAX30105_MODECONFIG);
如果((RESPONSE & MAX30105_RESET)= 0)中断;//我们完成!
SysCtlDelay (延迟);//let 不会使 I2C 总线过载
}
//在此放置一些延迟
}
void Sensorsetup (uint8_t powerLevel、uint8_t sampleAsyage、uint8_t ledMode、int sampleRate、int pulsewidth、 int adcRange){
softReset ();//将所有配置、阈值和数据寄存器重置为 POR 值
//FIFO 配置
/../../====================================================================================================================================================================================================================================================================
每片 FIFO 平均值(如果您希望)多个采样值为0或0、则为1个采样
值)
否则、如果(sampleAime== 4)设置 FIFOAime(MAX30105_SAMPLEAVG_4);
否则、如果(sampleAime=8)设置 FIFOAull (MAX30105_SAMPLEAVG_8);
否则、如果(sampleAime=16)设置 FIFOA105 (MAX30105_SAMPLEG_8
);如果(samples/sameAM30_SAAVAime32);设置为"/sameAVEAPeEXOLAY=16);
//Allow FIFO to wrap/roll over
//================================/Mode
Configuration /============================================================================================================================================================================================================================================================================
RedleMode=(仅限三个)/TIRELED-MODE=EMEND30105;ENDULLE=(仅限三个)/RELED-MODE=EMENDULLE/EMEND23)
//用于控制从 FIFO 缓冲区中读取的字节数
//====================================================================================
Parsensing Configuration /============================================================================================================================ Range
S= ADC30384Sb RAC18248Sb (Sb) Range = XADC18245;= END= R18245S= END=(Sb) SENS=S=30245S=S=ENDA-=(S= RAC18245S=) SENS=S=(S=)
如果(sampleRate < 100) setSampleRate (MAX30105_SAMPLERATE_50);//如果
(sampleRate < 200) setSampleRate (MAX30105_SAMPLERATE_100);
否则(sampleRate < 400) sampleR100 (sampleR100
);如果(sampleR100
) sampleR100 (sampleR100
) sampleR100 (sampleR100);如果(sampleR100_SAMP30105_SAMPR100) sampleR100) sample_sample_sample_100 (sample_100);如果(sampleR100 (sampleR100) sampleR100 (sampleR100) sampleR100 (sampleR100) sampleR100 (sampleR100);如果(sampleR100) sample_sample_sample_sample_sample_sampleR100 (sampleR100) sample_s
否则、如果(sampleRate == 3200) setSampleRate (MAX30105_SAMPLERATE_3200);
否则、setSampleRate (MAX30105_SAMPLERATE_50);
//脉宽越长、检测距离越长、
在69us 和0.4mA 时、检测距离就大约为2英寸
//16英寸
(如果为0.4mA)、则为1 x 6英寸/0 x 6英寸(1 x 6英寸)。 //第26页,如果
(pulsewidth < 215)设置 PulseWidth (MAX30105_pulsewidth_118),则获得15位分辨率;//如果
(pulsewidth <)设置 PulseWidth (MAX30105_pulsewidth_215),则获得16位分辨率
;//如果(pulsewidth = 105)设置 PulseWidth (MAX301051_1011_set14),则获得17位分辨率;/PulseWidth_10411_setMAX30411_resolution
;//设置 Pulse411_10411_PulseWidth_resolution;//
//--========================================/LED
脉冲振幅配置
/=================================================================================================================================================== 0x42mA-0X46mA-0X4mA/powerel=0x4mA/enitude
~
~
~……………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………
50.0mA -~12英寸
setPulseAmplitudeRed (powerLevel)的存在检测;
setPulseAmplitudeIR (powerLevel);
setPulseAmplitudeGreen (powerLevel);
setPulseAmplitudeLED (powerLevel);
/--=-=/enableSlot
1);/=/=enable_enableMode (enableSlot 1);/=/=-=/=/enableSlot =/=/enableLED (enable_enable_enableMode);/=/=/=/=/enableSlot (enable=/=/=/enable= 1)/=/=/enable/=/enableSlot (enableMode)/=/=/=/enable/=/=/=/enableSlot (enable3)/=/enable/=/=/enableMode)/=/enable/enable/=/=/=/enableSlot (enable3)/enableLED (enable/=/=/=/enableSlot_enable
SLOT_IR_Pilot);
//enableSlot (3、SLOT_GREEN_PIRER);
//--============================================================================================================================================================================-----
--------------clearFIFO ();//在我们开始检查一
个二进制或六进制数之前重置传感器。 读出帧的最后一位数字。
void binary (n){
while (n){
如果(n 和1)
UARTprintf ("1");
其他
UARTprintf ("0");
n >=1;
}
UARTprintf ("\n");
}
//initialize I2C module 0
// TI 示例代码
void InitI2C0 (void)
{的细微修改版本
//启用 I2C 模块0
SysCtlPeripheralEnable (SYSCTL_Periph_I2C0);
//复位模块
//SysCtlPeripheralReset (SYSCTL_Periph_I2C0);
//启用包含 I2C 0的 GPIO 外设
SysCtlPeripheralEnable (SYSCTL_Periph_GPIOB);
//added 等待外设为编程做好准备
while (!SysCtlPeripheralReady (SYSCTL_Periph_GPIOB));
//为端口 B2和 B3上的 I2C0功能配置引脚复用。
GPIOPinConfigure (GPIO_PB2_I2C0SCL);
GPIOPinConfigure (GPIO_PB3_I2C0SDA);
//为这些引脚选择 I2C 功能。
GPIOPinTypeI2CSCL (GPIO_PORTB_BASE、GPIO_PIN_2);//I2C0 SCL
GPIOPinTypeI2C (GPIO_PORTB_BASE、GPIO_PIN_3);//I2C0 SCL
//启用和初始化 I2C0主机模块。 使用的系统时钟
// I2C0模块。 最后一个参数设置 I2C 数据传输速率。
//如果为 false,则数据速率设置为100kbps,如果为 true,则数据速率将设置为
//设置为400kbps。
#if defined (target_IS_TM4C129_RA0)|| \
已定义(TARGET_IS_TM4C129_RA1)|| \
已定义(TARGET_IS_TM4C129_RA2)
I2CMasterInitExpClk (I2C0_BASE、ui32SysClock、false);
#else
I2CMasterInitExpClk (I2C0_BASE、SysCtlClockGet ()、false);
#endif
//清除 I2C FIFO
//HWREG (I2C0_BASE + I2C_O_FIFOCTL)= 80008000;
}
空 InitConsole (void){
//启用用于 UART0引脚的 GPIO 端口 A。
// TODO:将其更改为您正在使用的 GPIO 端口。
SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA);
//为端口 A0和 A1上的 UART0功能配置引脚复用。
//如果您的器件不支持引脚复用、则无需执行此步骤。
// TODO:更改此选项以选择您正在使用的端口/引脚。
GPIOPinConfigure (GPIO_PA0_U0RX);
GPIOPinConfigure (GPIO_PA1_U0TX);
//启用 UART0以便我们可以配置时钟。
SysCtlPeripheralEnable (SYSCTL_Periph_UART0);
//使用内部16MHz 振荡器作为 UART 时钟源。
UARTClockSourceSet (UART0_BASE、UART_CLOCK_PIOSC);
//为这些引脚选择替代(UART)功能。
// TODO:更改此选项以选择您正在使用的端口/引脚。
GPIOPinTypeUART (GPIO_Porta_base、GPIO_PIN_0 | GPIO_PIN_1);
//初始化控制台 I/O 的 UART
UARTStdioConfig (0、115200、16000000);
}
void main (){
ui32SysClock = MAP_SysCtlClockFreqSet ((SYSCTL_XTAL_25MHz |
SYSCTL_OSC_MAIN | SYSCTL_USE_PLL |
SYSCTL_CFG_VCO_480)、120000000);
InitConsole ();
InitI2C0 ();
//Sensorsetup (0xFF、4、2、100、411、4096);
softReset();
I2CSOEND (I2CDEVICE_ADDR,2,MAX30105_MODECONFIG,0x02); //心率
SysCtlDelay (延迟);
I2CSend (I2CDEVICE_ADDR,2,MAX30105_LED1_PULSEAMP,0x01);//用118us 打开红色 LED。
while (1){
RxData = I2CReceive (I2CDEVICE_ADDR、MAX30105_PARTID);
UARTprintf ("部件 ID 为:%x\n"、RxData);
SysCtlDelay (5*Delay);
}
附加的是 I2CEnd 的范围视图(I2CDEVICE_ADDR、2、MAX30105_LED1_PULSEAMP、0x01)
