我有一个工作的I2C与加速计连接到开发板。
初始化后的通信工作。
在该单元转到Extended_sleep之后并唤醒I2C不再工作。目前只有I2C上的一个设备。电源未禁用。
任务被困在ad_i2c.c:284 OS_事件等待(dev_config->bus_data->EVENT,OS_EVENT_EVENT);
中断触发一次,但我无法清除它,因为我需要读取地址以清除加速计侧的引脚。因此,加速度计似乎仍在工作。
我有I2C_总线_init(I2C1)和I2C_设备_init(ACCEL_KXCJB)的一次初始化。
platform_devices.h包含
I2C_BUS (I2C1)
I2C_SLAVE_DEVICE(I2C1, ACCEL_KXCJB, 0x0E)
硬件I2C硬件寻址7B,硬件I2C硬件速度快);
I2C_BUS_END
periph_init()包含(使用HW_GPIO_PINCONFIG宏,以便正确扩展名称)
hw_gpio_configure_pin(HW_GPIO_PORT_3, HW_GPIO_PIN_0, INPUT, I2C_SDA, false);/ / IC21数据
hw_gpio_configure_pin(hw_gpio_port_4,hw_gpio_pin_7,输出,i2c_scl,false);// i2c1 clk.
硬件gpio配置引脚(硬件gpio端口4,硬件gpio引脚3,输入,gpio,假);//加速irq
醒来后,示例说要改变线条。在Periph_init()中是否需要在延长睡眠后缺少I2C通信的情况下进行任何其他需要完成。
谢谢你的帮助。
设备:
我探测了SCL线路,在长时间睡眠后线路上没有任何活动。
你好理查德•Legault
我看不到您提到的配置中缺少任何内容,您如何触发系统中的传感器内存读取等?设备暂停的代码部分是因为它等待I2C模块的完整事件,但显然什么也没有发生。
另外,请看下面的帖子,也许这会有所帮助:
https://support.dialog-semicondiondiondum/forums/post/dialog-smartbond-bl ...
由于MT_dialog
当I2C脱离睡眠状态时,其状态为0(禁用)。
要使I2C再次正常工作,仅执行hw_I2C_启用(hw_I2C1)是不够的,我还必须初始化总线并设置目标地址。
因此,I2C Periph_Init的代码现在:
=================
hw_gpio_configure_pin(HW_GPIO_PORT_3, HW_GPIO_PIN_0, INPUT, I2C_SDA, false);/ / IC21数据
hw_gpio_configure_pin(hw_gpio_port_4,hw_gpio_pin_7,输出,i2c_scl,false);// i2c1 clk.
硬件gpio配置引脚(硬件gpio端口4,硬件gpio引脚3,输入,gpio,假);//加速irq
静态const i2c_config cfg = {
。speed = HW_I2C_SPEED_FAST,
.mode = hw_i2c_mode_master,
.addr_mode=HW_I2C_寻址_7B,
};
hw_i2c_init(hw_I2C1和cfg);
hw_i2c_set_target_address (HW_I2C1 0 x0e);/*显示适配器没有设置地址时,只有一个I2C设备在总线上?*/
硬件单元i2c硬件单元启用(硬件单元I2C1);
====================.
在示例或文档中没有提到这些初始化步骤需要在睡眠结束时完成。我只是在之前的回复中发现了这个链接。
问题是:深度睡眠后的正常行为是否需要初始化,或者这是i2c适配器或hw_i2c代码中的错误。即使只有一个设备的总线,适配器也会更新设备地址吗。
为什么当适配器假设为我这样做时,我必须设置目标Address?如果我没有在init中设置地址,那么我可以为设备读取所有寄存器的值0x07。这是仅在总线上具有一个设备的工件。
你好理查德•Legault
如前所述先前有直接回答这些初始化并不必要,因为你正在使用适配器来与传感器交互,适配器将重新启用和配置I2C总线,您只需要将配置你的别针periph_setup()函数。因此,如果您正在使用适配器,您只需要使用ad_i2c_open()打开在platform_devices.h中声明的I2C设备的连接,并使用ad_i2c_transact()或ad_i2c_write()、ad_i2c_read()等启动一个事务。那么如何触发事务呢?
由于MT_dialog
是的,这是预期的行为,但观察到的行为是我确实需要做那些3个步骤,否则I2C在延长睡眠时醒来时没有响应。
嗨,理查德
如果您调用我上面提到的一个函数来启动与I2C模块的交互,那么这就是系统的预期行为
调用AD_I2C_BUS_AQUIRE()函数,ad_i2c_bus_apply_config()将为当前事务配置I2C模块(HW_I2C_INIT()/ hw_i2c_enable()
将对当前事务执行,主目标地址也将从hw_i2c_init()设置。所以如果这是你唯一能做到的
I2C通信可能您不使用适配器来触发I2C交互。例如,我定期从RTOS定时器读取传感器的值,所以
系统醒来,通过下面的功能,我可以读出传感器的名称。
/ *从传感器读取单独的阅读和写交易* /
void read_mpu_reg_rw(uint8_t reg_addr)
{
静态uint8\u t who\u i\u am\u rw=0;
uint8\u t addr=注册地址;
mpu6050 = ad_i2c_open (MPU_6050);
ad_i2c_写入(mpu6050,®_地址,1);
ad_i2c_read(mpu6050和who_i_am_rw,1);
printf (" % 02 x r \ n \”,who_i_am_rw);
}
由于MT_dialog
是的,我开了一个开放。交易呼叫永远不会返回,因为它正在等待I2C完成。我用书写和读数替换了交易,但观察到的行为仍然是相同的。SDK为DA14681为1.0.8.1050.1
谢谢你与此保持一致。我很困惑为什么我在延长睡眠后没有看到预期的行为。
顺便说一下,当我执行HW_I2C_GET_ENABLE_STATUS_STATUS_STATUS()后,延长睡眠后返回0,除非我在PERIPH_INIT中有3个不必要的步骤。
在I2C_Handler()调用I2C-> Intr_CB的值为null。
我没有改变任何保留设置,但看起来I2C的内存(状态)在延长睡眠期间丢失了。
可能是什么原因导致了这种行为?请注意,我们已将8MBit winbond替换为64MBit winbond闪存部件。我们为此创建了新的适当标题文件。
#定义proj_configOPTIMAL_RETRAM (0)
#if !define (RELEASE_BUILD) && (proj_configOPTIMAL_RETRAM == 1)
/ *警告:在调试版本中禁用了鼠尾优化!*/
#undef proj_configoptimal_retram.
#定义proj_configOPTIMAL_RETRAM (0)
#elif(dg_configexec_mode!= mode_is_cached)
/ *警告:对镜像模式不适用于逆流优化!*/
#undef proj_configoptimal_retram.
#定义proj_configOPTIMAL_RETRAM (0)
#万一
#如果(项目配置优化再培训==0)
#定义dg_配置内存保留模式(0x1F)
#定义dg_配置洗牌_模式(0x3)
嗨,理查德,
你能告诉我,你如何在代码中触发I2C事务,为了让设备开始交互,你将代码放置在哪里?
由于MT_dialog
它位于被中断唤醒的任务中。在前面的响应中,我向kxcjbDevRegisterGet显示了调用链。
由于中断不能使用适配器与I2C交互,因此当通过I2C读取中断清除寄存器时,任务必须清除中断。
这是中断处理程序(HW GPIO的清除由我写的WKUP处理程序完成。任务在检测到某个端口/引脚中断时,使用WKUP寄存器。
//它的想法是,这是中断的上半部分,它发出信号让下半部分(任务)在稍后的时间运行。
静态void kxcjbtapeventintr>(void * enceData)
{
// tp_interrupteventdata p_eventdata =(tp_interrupteventdata)eventData;
BaseType_t xhigherprioritytaskkoken = pdFALSE;
xtasknotifyfromisr(AccelIntractTaskHandle,Accel_Intr_Notify,Esetbits,
&xHIGHERPRIORITYTASKWAKEN);
portyield_from_isr(xhigherprioritytaskwoken);
返回;
}
//这就是任务//
//其思想是,这是计划在以后运行的中断的下半部分。
静态void accelTaskHL(void*pvParameters)
{
/*定义静态变量以使其脱离堆栈*/
静态uint8_t加速度源[2];
t_errorCode errCode;
布尔街;
bool dataValid = false;
uint32_t notifyValue;
UINT8_T数据;
const timerhandle_t acceltimer = xtimercreate(“AcceltaskTimer”,
pdMS_至_刻度(750),
pdfalse,
(void *)0,
acceltimercallback);
而(1)
{
xTaskNotifyWait(0x00,ULONG_MAX,¬ifyValue,portMAX_DELAY);//在此处等待下一个信号:中断、超时或控制消息
kxcjbDevRegisterGet(NULL、WHOAMI_ADDR和data);//在这个函数中,我执行ad_i2c_transact()
if(notifyValue和ACCEL\u ENABLE\u NOTIFY){
g_加速度状态=加速度状态0;
kxcjbinterruptenable();
i2c_device dev = ad_i2c_open(Accel_kxcjb);
errCode=kxcjbBitsSet(dev、CTRL\u REG1\u ADDR、CTRL\u REG1\u PC1\u EN);
断言(errcode == errercode_ok);
ad_i2c_close (dev);
}
否则如果(notifyValue&ACCEL\u DISABLE\u NOTIFY){
kxcjbinterruptdisable();
i2c_device dev = ad_i2c_open(Accel_kxcjb);
errCode = kxcjbbitclear (dev, CTRL_REG1_ADDR, CTRL_REG1_PC1_EN);
断言(errcode == errercode_ok);
ad_i2c_close (dev);
g_accelState=加速状态_禁用;
}
其他的
{
开关(g_加速状态){
案例ACCEL_STATE_DISABLE:
/*什么都不做*/
打破
案例加速状态0:
if (notifyValue & ACCEL_INTR_NOTIFY) {
kxcjbinterruptsrc(null,&accelsource [Accel_State_0]);
/*将处理计时器已经在运行的情况,
*不应该发生
*/
Xtimerreset(Acceltimer,0);
g_accelState=加速状态_1;
}
/*否则我们将忽略计时器中断,不应发生*/
打破
案例加速状态1:
if (notifyValue & ACCEL_INTR_NOTIFY) {
kxcjbInterruptSrc(NULL,&accelSource[ACCEL_STATE_1]);
printf(“0=0x%02x\n\r1=0x%02x\n\r”,accelSource[0],accelSource[1]);
fflush(stdout);
/*测试源中断是否在同一轴上
*正如在上一次中断中发生的那样
*/
如果(((accelSource (ACCEL_STATE_0) & (INT_SOURCE2_XPWU | INT_SOURCE2_XNWU))
&&(accelSource[ACCEL_STATE_1]和(INT_SOURCE2_XPWU | INT_SOURCE2_XNWU))
) ||
((Accelsource [Accel_State_0]&(Int_source2_ypwu | Int_source2_ynwu))
&&(Accelsource [Accel_State_1]&(Int_source2_ypwu | Int_source2_ynwu))
) ||
((Accelsource [Accel_State_0]&(Int_source2_zpwu | Int_source2_znwu))
&&(Accelsource [Accel_State_1]&(Int_source2_zpwu | Int_source2_znwu))
)
){
xTimerStop(加速计时器,0);
if(Accel_Task_disable_on_tap_detect){
g_accelstate = Accel_State_disable;
kxcjbinterruptdisable();
}
别的 {
g_accelState = ACCEL_STATE_0;
}
if(gfp_tapeventcb){
gfp_tapEventCb (g_appInfo);
}
}
别的 {
printf(“AC:TO\n\r”);
fflush(stdout);
Xtimerreset(Acceltimer,0);
accelSource [ACCEL_STATE_0] = accelSource [ACCEL_STATE_1];
g_accelstate = Accel_State_1;/ *重新输入相同的状态* /
}
}
否则如果(notifyValue&ACCEL\u TIMER\u NOTIFY){
g_加速度状态=加速度状态0;
}
别的 {
断言(0 = = 1);
}
}
}
}
}
//下面是创建任务的代码,
uint32_t status=OS_TASK_CREATE(“AccelInterruptHL”),指定给任务的文本名称,例如
只调试;内核不使用。*/
accelTaskHL,/*系统初始化任务*/
(void*)0,/*传递给任务的参数*/
configminimal_stack_size * os_stack_word_size * 2,
/ *分配给的字节数
任务的堆栈*/
OS_TASK_PRIORITY_HIGHEST, /*执行任务的优先级。*/
AccelInterractTaskHandle);/ *任务句柄* /
你好理查德•Legault
因此,您已经配置了唤醒计时器,以便触发来自附加传感器的传感器读数,每次传感器发出中断时,您就通知触发读取的任务,然后执行数据读取和清除中断。似乎ok,我不太明白的是唤醒中断的中断处理程序(我认为这是kxcjbTapEventInterrupt,我是正确的),为什么处理程序有一个事件参数?也不推荐调用portYIELD_FROM_ISR(虽然我已经测试它,至少在我身边不会影响I2C交互在睡眠模式)和你不应该运行一个任务优先级最高,因为这可能会影响其他任务(BLE的任务,任务管理器等)。无论如何,我不认为这些会导致任何问题的I2C,所以我的建议是调试这个,并检查代码是否通过I2C交互功能,我的意思是ad_i2c_read/write等,也,你提到的配置后睡眠是零,只要调用I2C交互函数ad_i2c_read/write等,就应用I2C模块的配置。也可以编写一个简单的代码来测试如果与i2c的交互简单项目(你可以通过一个简单的计时器与传感器交互或通过唤醒定时器触发中断gpio)并检查如果正在定制设备,与你现在。我注意到的最后一件事是,您使用的I2C引脚端口是PORT4和port3,请注意,如果您使用的是WCSP包,这些端口是不可用的。
由于MT_dialog
它似乎是由于使用gcc-arm-none-eabi-6-2017-q1-update(使用这个刀具链,我必须使用额外的步骤来获得I2c工作)。
随着提供的GCC工具链:4_9-2015Q3 I2C为广告工作。
感谢您的帮助和坚持不懈。
希望这可以节省他人的时间,知道工具链会影响文档的行为。
嗨,理查德,
谢谢你指出这一点,很高兴你解决了你的问题。
向MT_dialog致意