-
GD32F407 I2C通讯, 读取数据时候出现 AERR 标志
使用GD32F407调试I2C, 当主机接收最后一个数据前发送NAK会导致I2C进入AERR, 各位大大, 这个是正常的么?
1395浏览量 2回复量 关注量 -
ch32v103 c8t6 如何支持中断发送 sos
hi, 我根据https://bbs.21ic.com/icview-3141094-1-1.html sample代码,可以实现从机接收。(主机为RK3566, 从机CH32V103) 即主机可以i2c_write成功。 但如果调用 i2c_read, 则ch32v103会 一直拉低I2C CLK线,CH32只产生了三个中断,最后一个中断报ACK FAILED。 int R1:2 R2:2, TxCount:0 int R1:82 R2:6, TxCount:0 error int :480 6 I2C_IT_AF 出现以上问题后,必须复位CH32V103才会使I2C CLK线重新拉高。 请问是否有中断从机发的sample code. 目前代码如下: //下述中断程序中,当主机读取和写入数据时,都会引起地址位被置位,即发生EV1事件(即本中断处理程序中将发送和接收的EV1合并了); //当主机写入数据时,中断的执行顺序是EV1―>EV2―>EV4,其中有多个数据EV2会多次执行; //当主机读取数据时,中断的执行顺序是EV1―>EV3―>EV3-2,本中断程序中将EV3和EV3-1合并了,若有多个数据,EV3将多次执行。 //本程序只进行从机中断接收 //事件中断处理函数 void I2C1_EV_IRQHandler( void ) { uint16_t STAR1Register,STAR2Register; int i = 0; u8 rcv = 0; //状态寄存器1和状态寄存器2对应值 STAR1Register = I2C1->STAR1; STAR2Register = I2C1->STAR2; printf("int R1:%x R2:%x, TxCount:%d\r\n", STAR1Register, STAR2Register, TxCount); //I2C从机 (MSL = 0) //若状态寄存器2的位0不为1,即为0,则代表从模式(1代表主模式) if( ( STAR2Register & 0x0001 ) == 0x0000 ) { //从机发送数据 发送数据(TxE = 1: EV3、EV3-1) //从模式下,若状态寄存器1 位7 TxE位为1,则数据寄存器空 if( (STAR1Register & 0x0080) == 0x0080) { I2C1->DATAR = TxData[ TxCount ]; //printf("Tx:W reg:%x\r\n", TxData[ TxCount ]); TxCount++; STAR1Register = 0; STAR2Register = 0; //RxData[ RxCount ] = I2C1->DATAR; } //从模式下,若状态寄存器1 位1 ADDR的位为1,收到的地址匹配,即 主机已发送地址,地址为被置位・(ADDR = 1: EV1(包括发送和接收)) if( STAR1Register & 0x0002 ) { //清除相应值 STAR1Register = 0; STAR2Register = 0; RxCount = 0x00; TxCount = 0x00; } //从机接收到数据 (RXNE = 1: EV2) //从模式下,若状态寄存器1 位6 RxNE位为1,则数据寄存器非空 if( STAR1Register & 0x0040 ) { RxData[ RxCount ] = I2C1->DATAR; printf("40 rx reg:%x\r\n", RxData[RxCount]); RxCount++; STAR1Register = 0; STAR2Register = 0; } //从机接收到停止信号,检测到停止条件(STOPF =1: EV4) //从模式下,若状态寄存器1 位4 STOPF位为1,则检测到停止条件 if( STAR1Register & 0x0010 ) { //控制寄存器1 位0设置为1,启用IIC模块 I2C1->CTLR1 |= 0x0001; STAR1Register = 0; STAR2Register = 0; Rec_Finish_Flag = 0x01; } //从机发送数据 发送数据(TxE = 1: EV3、EV3-1) //从模式下,若状态寄存器1 位7 TxE位为1,则数据寄存器空 if( (STAR1Register & 0x0080) == 0x0080) { I2C1->DATAR = TxData[ TxCount ]; TxCount++; STAR1Register = 0; STAR2Register = 0; RxData[ RxCount ] = I2C1->DATAR; printf("rx reg:%x\r\n", RxData[RxCount]); } //从机接收非应答信号 检测到非应答(AF =1: EV3-2) //从模式下,若状态寄存器1 位10 AF位为1,则应答失败(当没有返回应答时,硬件将置该位为’1’) if( STAR1Register & 0x0400 ) { printf("event AF ERROR\r\n"); I2C1->STAR1 &= ~( 0x0400 ); //该位由软件写’0’清除,或在PE=0时由硬件清除。 I2C1->STAR1 &= ( 0xFDFF ); STAR1Register = 0; STAR2Register = 0; } } //printf("out int :%x %x, TxCount:%d\r\n", STAR1Register, STAR2Register, TxCount); } //错误中断处理函数 //下述程序中,发送各种错误进行错误中断不做对应的处理,最后只进行清除寄存器(STAR1和STAR2)操作。 void I2C1_ER_IRQHandler(void) { uint16_t STAR1Register,STAR2Register; //状态寄存器1和状态寄存器2对应值 STAR1Register = I2C1->STAR1; STAR2Register = I2C1->STAR2; printf("error int :%x %x\r\n", STAR1Register, STAR2Register); if(I2C_GetITStatus(I2C1, I2C_IT_SMBALERT)) { printf("I2C_IT_SMBALERT\r\n"); } else if(I2C_GetITStatus(I2C1, I2C_IT_TIMEOUT)) { printf("I2C_IT_TIMEOUT\r\n"); } else if(I2C_GetITStatus(I2C1, I2C_IT_PECERR)) { printf("I2C_IT_PECERR\r\n"); } else if(I2C_GetITStatus(I2C1, I2C_IT_OVR)) { printf("I2C_IT_OVR\r\n"); } else if(I2C_GetITStatus(I2C1, I2C_IT_AF)) { I2C_ClearITPendingBit(I2C1, I2C_IT_AF); I2C1->STAR1 &= ~( 0x0400 ); //该位由软件写’0’清除,或在PE=0时由硬件清除。 I2C1->STAR1 &= ( 0xFDFF ); STAR1Register = 0; STAR2Register = 0; printf("I2C_IT_AF\r\n"); //IIC_Init(g_bound, g_address); } else if(I2C_GetITStatus(I2C1, I2C_IT_ARLO)) { printf("I2C_IT_ARLO\r\n"); } else if(I2C_GetITStatus(I2C1, I2C_IT_BERR)) { printf("I2C_IT_BERR\r\n"); } //控制寄存器1 位0设置为1,启用IIC模块 I2C1->CTLR1 |= 0x0001; STAR1Register = 0; STAR2Register = 0; }
1654浏览量 0回复量 关注量 -
关于使用ov7725摄像头出现花屏问题
1.使用的是野火的摄像头模块,移植到龙芯1c平台的rtt系统上 2.将摄像头传输的数据显示在液晶屏上,发现出现花屏,即数据出现重复的现象 ![image.png](https://oss-club.rt-thread.org/uploads/20220509/07cae35e3c58f5f98f6d5d9f8438eca0.jpg.webp) [img]https://s1.328888.xyz/2022/05/09/4SNje.jpg[/img] 3.一些奇怪的地方: ①可以利用硬件i2c读取和写寄存器,但是,存在部分寄存器写入失败或者压根没有写入,即我写入寄存器数值后,再次读取该寄存器的内容时,发现与我写入的数值不一致,我循环的写入之后,写入成功,再一次读取该寄存器,发现部分寄存器还是不是我期待的内容 ![image.png](https://oss-club.rt-thread.org/uploads/20220509/aa1643cf9704bd40280819456a834140.jpg.webp) ②图像的帧率越来越低,到第27次时甚至停下了,总体上帧率也非常低(包括一开始) ![image.png](https://oss-club.rt-thread.org/uploads/20220509/8ed27e755b30a9b5d8604ea28fcff278.jpg.webp) {{image.png(uploading...)}}
1236浏览量 1回复量 关注量 -
这两个MOS管在电路中起什么作用?
[i=s] 本帖最后由 Q1011503783 于 2021-10-20 17:33 编辑 [/i] [attach]1774938[/attach]I2C电路,这两个MOS管在电路中起什么作用?[url=]360截图1619081467109105.p ...[/url]
4879浏览量 8回复量 关注量 -
GD32E503硬件I2C问题
求大佬们帮忙看看[img]https://bbs.21ic.com/static/image/smiley/comcom/9.gif[/img]刚开始搞编程,最近在学习GD32E503-Start的开发板,按照官方提供的固件库使用指南操作在使用硬件I2C的时候发现ADDSEND位一直不置1,导致程序一直卡在 [color=#f00000]while(!i2c_flag_get(i2c_periph,I2C_FLAG_ADDSEND));[/color] 检查硬件连接也没啥问题,把程序下进去之后,疯狂按复位,发现有那么几次ADDSEND被置1了,真的搞不清楚什么情况,求各位帮忙看看,代码是按照官方提供的例程写的,使用的是I2C1,PB10,PB11引脚 void lmp_reg_write(uint32_t i2c_periph, uint32_t lmp_reg, uint8_t datatransmit) { while(i2c_flag_get(i2c_periph,I2C_FLAG_I2CBSY)); i2c_start_on_bus(i2c_periph); while(!i2c_flag_get(i2c_periph,I2C_FLAG_SBSEND)); i2c_master_addressing(i2c_periph,LMP_ADDR_WRITE,I2C_TRANSMITTER); [color=#f00000]while(!i2c_flag_get(i2c_periph,I2C_FLAG_ADDSEND));[/color] i2c_flag_clear(i2c_periph,I2C_FLAG_ADDSEND); while(!i2c_flag_get(i2c_periph,I2C_FLAG_TBE)); i2c_data_transmit(i2c_periph,lmp_reg); while(!i2c_flag_get(i2c_periph,I2C_FLAG_TBE)); i2c_data_transmit(i2c_periph,datatransmit); while(!i2c_flag_get(i2c_periph,I2C_FLAG_BTC)); i2c_stop_on_bus(i2c_periph); while(I2C_CTL0(i2c_periph)&0x0200); } 供电我是直接用usb线到电脑上,连的gd-link那个usb口,也方便烧录。
4861浏览量 4回复量 关注量 -
【请教】关于 PCA9555 芯片 I2C 通讯挂死的奇怪问题 sos
[i=s] 本帖最后由 villivateur 于 2021-7-10 17:13 编辑 [/i] 最近的项目正在使用 STM32F103RC 和 PCA9555 芯片。 PCA9555 芯片的 port0 用于监控一个 4x4 的矩阵键盘(故 GPIO 低四位是输出模式,高四位是输入模式);port1 用于向外接并口显示屏写数据(故 GPIO 八位均为输出模式)。 STM32(使用 FreeRTOS) 通过 I2C 与 9555 通讯(使用了 STM32 的 I2C 控制器,非 GPIO 模拟),400kbps 速率。键盘监听和写显示屏是两个线程,通过信号量保证 I2C 读写不冲突。 [b]问题出现了:程序运行后,I2C 必现 SDA 被拉低挂死,必须重置 PCA9555 才能恢复,但下次启动又会被挂死。[/b] [b]奇怪的现象是,如果我把 PCA9555 port1 的最高位初始化为输入模式,同样的代码,就不会出现任何问题。[/b] 同样的,删掉键盘监听线程(或者删掉监听线程里面读 I2C 的部分),也不会挂死;单独删掉显示屏线程,仍然会挂死。 我的代码: 1. 初始化键盘相关: [code]void keyboard_gpio_init() { PCA9555_WriteByte(PCA9555_OUTPUT_PORT0, 0x00); PCA9555_WriteByte(PCA9555_CONF_PORT0, 0xF0); // port 0 is keyboard }[/code]2. 初始化显示屏相关: [code]void tmf_lcd_gpio_init() { GPIO_InitTypeDef LCD_InitStructure; RCC_APB2PeriphClockCmd(LCD_CLK, ENABLE); LCD_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; LCD_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; LCD_InitStructure.GPIO_Pin = LCD_RS | LCD_RW | LCD_E | LCD_PSB | LCD_RST; GPIO_Init(LCD_PORT, &LCD_InitStructure); PCA9555_WriteByte(PCA9555_OUTPUT_PORT1, 0x00); PCA9555_WriteByte(PCA9555_CONF_PORT1, 0x00); // port 1 is lcd }[/code][color=#F00000][b]注意,此处如果把最后一行的 0x00 改成 0x80 或者 0xF0 等等,故障均会消失。[/b][/color] [color=#F00000][color=#000000]3. 键盘监听的部分代码:[/color][/color] [code]static inline uint8_t keyboard_get_col(void) { uint8_t data = 0xff; if (PCA9555_ReadByte(PCA9555_INPUT_PORT0, &data) != 0) { return 0xff; } if (data & KEYBOARD_COL0) { return 0x00; } if (data & KEYBOARD_COL1) { return 0x01; } if (data & KEYBOARD_COL2) { return 0x02; } if (data & KEYBOARD_COL3) { return 0x03; } return 0xff; } TMF_CMD keyboard_get_pressed(void) { uint8_t col; TMF_CMD pressed; uint8_t pressed_index; uint8_t flag=0; // 四行扫描完成之后 是否有按键 if (PCA9555_WriteByte(PCA9555_OUTPUT_PORT0, KEYBOARD_ROW0) != 0) { return TMF_CMD_NONE; } col = keyboard_get_col(); // 这一行可以成功执行,执行完后就挂死了 if(col!=0xff){ pressed_index = 0x00+col; flag = 1; } ......[/code]4. PCA9555 驱动请见 https://drive.vvzero.com/s/X8CNkkSKNzYqMbX 请问,是我哪里没搞对吗?
4554浏览量 0回复量 关注量 -
imx6 driver->suspend sos
imx6在使用时,编译的内核发现i2c系统好像没起来,内核部分打印信息如下[align=left]mc_pfuze 1-0008: recv failed!:-5,80 [/align][font=等线][size=10.5pt]mc_pfuze: probe of 1-0008 failed with error -1[/size][/font] [font=等线]上两句好像是电源问题[/font] [align=left]i2c-core: driver [isl29023] using legacysuspend method [/align][font=等线][size=10.5pt]i2c-core: driver [isl29023] using legacy resumemethod[/size][/font] [font=等线][size=10.5pt]查了i2c-core源码如下[/size][/font] [font=等线][size=10.5pt] [/size][/font][font=等线]if (driver->suspend)[/font] [font=等线] pr_warn("i2c-core: driver [%s] using legacy suspend method\n",[/font] [font=等线] driver->driver.name);[/font] [font=等线] if (driver->resume)[/font] [font=等线] pr_warn("i2c-core: driver [%s] using legacy resume method\n",[/font] [font=等线] driver->driver.name);[/font] [font=等线]想问一下什么情况下这个[/font][font=等线]driver->suspend、[/font][font=等线]driver->resume会生效,他生效代表什么意思[/font]
1391浏览量 0回复量 关注量 -
AT32F421F4P7 硬件IIC从机例程 (I2C2)
请问哪里有AT32F421F4P7 硬件IIC从机例程 (I2C2)?AT32F413调好的程序移植过来进不去从机中断,求救~~~
2929浏览量 1回复量 关注量 -
GD32F的IIC模块读取是,读的字节数为2,将I2C_CTL0的POAP置为1?
GD32F103的IIC模块在进行eeprom读取的时候,当读取的字节数为2时,需要将I2C_CTL0的POAP置为1;POAP的定义如下: 0:ACKEN位决定对当前正在接收的字节发送ACK; 1: ACKEN位决定是否对下一个字节发送ACK. 我的理解时:当读取的字节数为2时,该位置1,表示接收第一个字节后,发送ACK;接收第二个字节后,不发送ACK。这样就能保证时序的正确性。 不知道各位大佬是如何理解的,请赐教。谢谢! 代码如下: void eeprom_buffer_read(uint8_t* p_buffer, uint8_t read_address, uint16_t number_of_byte) { /* wait until I2C bus is idle */ while(i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)); if(2 == number_of_byte) { i2c_ackpos_config(I2C0,I2C_ACKPOS_NEXT); //如果接收的的字节数等于2,则将将I2C_CTL0的POAP置为1。 } /* send a start condition to I2C bus */ i2c_start_on_bus(I2C0); /* wait until SBSEND bit is set */ while(!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)); /* send slave address to I2C bus */ i2c_master_addressing(I2C0, eeprom_address, I2C_TRANSMITTER); /* wait until ADDSEND bit is set */ while(!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)); /* clear the ADDSEND bit */ i2c_flag_clear(I2C0,I2C_FLAG_ADDSEND); /* wait until the transmit data buffer is empty */ while(SET != i2c_flag_get( I2C0 , I2C_FLAG_TBE)); /* enable I2C0*/ i2c_enable(I2C0); /* send the EEPROM's internal address to write to */ i2c_data_transmit(I2C0, read_address); /* wait until BTC bit is set */ while(!i2c_flag_get(I2C0, I2C_FLAG_BTC)); /* send a start condition to I2C bus */ i2c_start_on_bus(I2C0); /* wait until SBSEND bit is set */ while(!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)); /* send slave address to I2C bus */ i2c_master_addressing(I2C0, eeprom_address, I2C_RECEIVER); if(number_of_byte < 3){ /* disable acknowledge */ i2c_ack_config(I2C0,I2C_ACK_DISABLE); } /* wait until ADDSEND bit is set */ while(!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)); /* clear the ADDSEND bit */ i2c_flag_clear(I2C0,I2C_FLAG_ADDSEND); if(1 == number_of_byte){ /* send a stop condition to I2C bus */ i2c_stop_on_bus(I2C0); } /* while there is data to be read */ while(number_of_byte){ if(3 == number_of_byte){ /* wait until BTC bit is set */ while(!i2c_flag_get(I2C0, I2C_FLAG_BTC)); /* disable acknowledge */ i2c_ack_config(I2C0,I2C_ACK_DISABLE); } if(2 == number_of_byte){ /* wait until BTC bit is set */ while(!i2c_flag_get(I2C0, I2C_FLAG_BTC)); /* send a stop condition to I2C bus */ i2c_stop_on_bus(I2C0); } /* wait until the RBNE bit is set and clear it */ if(i2c_flag_get(I2C0, I2C_FLAG_RBNE)){ /* read a byte from the EEPROM */ *p_buffer = i2c_data_receive(I2C0); /* point to the next location where the byte read will be saved */ p_buffer++; /* decrement the read bytes counter */ number_of_byte--; } } /* wait until the stop condition is finished */ while(I2C_CTL0(I2C0)&0x0200); /* enable acknowledge */ i2c_ack_config(I2C0,I2C_ACK_ENABLE); i2c_ackpos_config(I2C0,I2C_ACKPOS_CURRENT); }
3034浏览量 2回复量 关注量 -
CC2640的I2C问题请教
我用CC2640 的I2C 模块给OPT3001光照芯片 写值,发现写不进去。该芯片寄存器是16位的,咱I2C模块可以写16位寄存器的值吗??? 我就想给0x01寄存器写个0x54,0x10,代码如下: void Set_OPT3001(uint8_t limit) { Reset_OPT3001_Register(); txBuffer[0] = 0x54;txBuffer[1] = 0x10; i2cTrans.writeCount = 3; i2cTrans.writeBuf = txBuffer; i2cTrans.readCount = 0; i2cTrans.readBuf = rxBuffer; i2cTrans.slaveAddress = 0x44; I2C_transfer(handle, &i2cTrans); }
21308浏览量 4回复量 关注量 -
CC2640的I2C问题?
我用CC2640的I2C操作寄存器读写值,示波器抓不到要写值的波形(可以抓到从机地址和寄存器地址),但是值可以写进去。这是什么原因呢,困扰了我好久了。求大神解答~I2C传输就用的官方的I2C_transfer函数
10262浏览量 1回复量 关注量 -
有人在用GDE230这款芯片吗?软硬件冲突好像特别严重
最近在用GDE230这款芯片,在调试外设时,串口,SPI,I2C,定时器,都没问题,但是只要综合起来,就会有一大堆问题,按照ST的开发流程,踩雷断腿搜索 [align=left]复制[/align]
1127浏览量 2回复量 关注量