问答

汇集网友智慧,解决技术难题

21ic问答首页 - GD32 F4硬件I2C总是锁死

GD32 国产芯片 嵌入式 MUC

GD32 F4硬件I2C总是锁死

jacket1232022-10-22
1.问题描述买了一个磁力计模块,用杜邦线连接到427start开发板,参考网上各种例程一直失败,要么是ADSEND不置1 ,要么是I2C总线一直忙,反复置位或者上电重启能读到一次,今天尝试了参考官方EEPROM的延时检测程序,还是没办法实现,求解求解!!
2.代码
代码1:未加延时检测代码
         while(i2c_flag_get(I2C1, I2C_FLAG_I2CBSY));
    printf("I2C bus is idle\r\n");
    i2c_start_on_bus(I2C1);   
    while(!i2c_flag_get(I2C1, I2C_FLAG_SBSEND));
    printf("SBSEND bit is set\r\n");
    i2c_master_addressing(I2C1, QMC5883L_DEFAULT_ADDRESS, I2C_RECEIVER);       
    while(!i2c_flag_get(I2C1, I2C_FLAG_ADDSEND));
    printf("ADDSEND bit is set\r\n");
    i2c_flag_clear(I2C1, I2C_FLAG_ADDSEND);
    i2c_ack_config(I2C1,I2C_ACK_DISABLE);
    i2c_stop_on_bus(I2C1);
    while(!i2c_flag_get(I2C1, I2C_FLAG_RBNE));
    printf("I2C_FLAG_RBNE bit is set\r\n");
    chipID = i2c_data_receive(I2C1);
        printf("0x %u \r\n",chipID);


++++++++++++++++++++++++++++++++++++++++++++++++
代码2延时检测
/*!
    \file    main.c
    \brief   GPIO running led demo

    \version 2022-04-26, V2.0.0, demo for GD32F4xx
*/

/*
    Copyright (c) 2022, GigaDevice Semiconductor Inc.

    Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice, this
       list of conditions and the following disclaimer.
    2. Redistributions in binary form must reproduce the above copyright notice,
       this list of conditions and the following disclaimer in the documentation
       and/or other materials provided with the distribution.
    3. Neither the name of the copyright holder nor the names of its contributors
       may be used to endorse or promote products derived from this software without
       specific prior written permission.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/

#include "gd32f4xx.h"
#include "gd32f4xx_timer.h"
#include "gd32f4xx_rcu.h"
#include "systick.h"
#include <stdio.h>
#include "gpio.h"
#include "usart.h"
#include "time.h"
#include "QMC5883L.h"
#include <stdbool.h>
#include "i2c.h"
/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
volatile uint32_t time =0;
uint8_t u_buf[256];
uint8_t USART1_RX_BUF[USART1_REC_LEN];
uint16_t USART1_RX_STA = 0;
bool ConnectionRsult;
uint8_t chipID=0x01;
uint8_t i2c_receiver[16];
uint8_t  i;

#define I2C_TIME_OUT    (uint16_t)(5000)
#define I2C_OK          1
#define I2C_FAIL        0
#define I2C_END         1



/* USER CODE END PV */
/*!
    \brief      main function
    \param[in]  none
    \param[out] none
    \retval     none
*/
uint8_t buffer_read_timeout(uint8_t *p_bufer,uint8_t read_address,uint16_t number_of_byte);

int main(void)
{
    /* configure systick */
    systick_config();
    /* configure GPIO */
    GD_GPIO_Init();
    /* configure         Timer1 */
    // GD_TIMER1_Init();
    /* configure GPIO */
    GD_USART1_UART_Init();
    //printf("====USART CONFIGURED====\r\n ");
    /* configure QMC5883L I2C */
    printf("====I2C START====\r\n ");
    gpio_config();
    i2c_config();
                buffer_read_timeout(i2c_receiver,0x0D,16);
    printf("0x%02X\r\n",chipID);
    /* System initialisation */
    //  rcu_periph_clock_enable(RCU_TIMER1);
    while(1)
    {

                }
}


uint8_t buffer_read_timeout(uint8_t *p_buffer,uint8_t read_address,uint16_t number_of_byte)
{
    uint8_t state=I2C_START;
    uint8_t read_cycle=0;
    uint16_t timeout=0;
    uint8_t i2c_timeout_flag=0;

    /* enable acknowledge */
    i2c_ack_config(I2C0, I2C_ACK_ENABLE);
    while(!(i2c_timeout_flag)){
        switch(state){
            case I2C_START:
                if(RESET==read_cycle){
                    /* i2c master sends start signal only when the bus is idle */
                    while(i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT)){
                        timeout++;
                    }
                    if(timeout<I2C_TIME_OUT){
                        if(2==number_of_byte){
                            /* whether to send ACK or not for the next byte */
                            i2c_ackpos_config(I2C0,I2C_ACKPOS_NEXT);
                        }
                    }else{
                        i2c_bus_reset();
                        timeout=0;
                        state=I2C_START;
                       // printf("i2c bus is busy in READ\r\n");
                    }
                }
                /* send the start signal */
                i2c_start_on_bus(I2C0);
                timeout=0;
                state=I2C_SEND_ADDRESS;
                break;
            case I2C_SEND_ADDRESS:
                /* i2c master sends START signal successfully */
                while((!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT)){
                    timeout++;
                }
                if(timeout<I2C_TIME_OUT)
                {
                    if(RESET==read_cycle)
                    {   
                        /*If it is the first time to execute here,
                        it should be the sending host address*/
                        i2c_master_addressing(I2C0,QMC5883L_DEFAULT_ADDRESS,I2C_TRANSMITTER);
                        state=I2C_CLEAR_ADDRESS_FLAG;
                    }else{
                        i2c_master_addressing(I2C0,QMC5883L_I2C_OWN_ADDRESS,I2C_RECEIVER);
                        if(number_of_byte<3){
                            /* disable acknowledge */
                            i2c_ack_config(I2C0, I2C_ACK_DISABLE);
                        }
                        state=I2C_CLEAR_ADDRESS_FLAG;
                    }
                    timeout=0;
                }else{
                    timeout=0;
                    state=I2C_START;
                    read_cycle = 0;
                   // printf("i2c master sends start signal timeout in READ!\r\n");
                }
                break;
            case I2C_CLEAR_ADDRESS_FLAG:
                /* address flag set means i2c slave sends ACK */
                 while((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT)){
                    timeout++;
                 }
                 if(timeout<I2C_TIME_OUT)
                 {
                    i2c_flag_clear(I2C0,I2C_FLAG_ADDSEND);
                    if((SET==read_cycle)&&(1==number_of_byte))
                    {
                        /* send a stop condition to I2C bus */
                        i2c_stop_on_bus(I2C0);
                    }
                    timeout=0;
                    state=I2C_TRANSMIT_DATA;
                 }else{
                    timeout=0;
                    state=I2C_START;
                    read_cycle=0;
                   // printf("i2c master clears address flag timeout in READ!\r\n");
                 }
                 break;
            case I2C_TRANSMIT_DATA:
                if(RESET==read_cycle)
                {
                    /* wait until the transmit data buffer is empty */
                    while((! i2c_flag_get(I2C0, I2C_FLAG_TBE)) && (timeout < I2C_TIME_OUT)){
                         timeout++;
                    }
                    if(timeout<I2C_TIME_OUT)
                    {
                        /* send the EEPROM's internal address to write to : only one byte address */
                        i2c_data_transmit(I2C0, read_address);
                        timeout=0;
                    }else{
                        timeout=0;
                        state=I2C_START;
                        read_cycle=0;
                      //  printf("i2c master wait data buffer is empty timeout in READ!\r\n");
                    }

                    while((!i2c_flag_get(I2C0, I2C_FLAG_BTC)) && (timeout < I2C_TIME_OUT)){
                        timeout++;
                    }
                    if(timeout < I2C_TIME_OUT){
                        timeout = 0;
                        state = I2C_START;
                        read_cycle++;
                    }else{
                        timeout = 0;
                        state = I2C_START;
                        read_cycle = 0;
                      //  printf("i2c master sends EEPROM's internal address timeout in READ!\r\n");
                    }
                }else{
                    while(number_of_byte){
                        timeout++;
                        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 RBNE bit is set */
                        if(i2c_flag_get(I2C0, I2C_FLAG_RBNE)){
                            /* read a byte from the EEPROM */
                            *p_buffer = i2c_data_receive(I2C0);
                            p_buffer++;
                            number_of_byte--;
                            timeout = 0;
                        }
                        if(timeout>I2C_TIME_OUT){
                            timeout=0;
                            state=I2C_START;
                            read_cycle=0;
                        //    printf("i2c master sends data timeout in READ!\r\n");
                        }
                    }
                    timeout=0;
                    state=I2C_STOP;
                }
                break;
            case I2C_STOP:
                /* i2c master sends STOP signal successfully */
                while((I2C_CTL0(I2C0) & I2C_CTL0_STOP) && (timeout < I2C_TIME_OUT)){
                    timeout++;
                }
                if(timeout < I2C_TIME_OUT){
                    timeout = 0;
                    state = I2C_END;
                    i2c_timeout_flag = I2C_OK;
                }else{
                    timeout = 0;
                    state=I2C_START;
                    read_cycle=0;
                 //   printf("i2c master sends stop signal timeout in READ!\r\n");
                }
                break;
            default:
                state = I2C_START;
                read_cycle = 0;
                i2c_timeout_flag = I2C_OK;
                timeout = 0;
             //   printf("i2c master sends start signal in READ.\r\n");
                break;

        }
    }
    return I2C_END;
}

+++++++++++++++++++++++++++++++++++++++++++++

回答 +关注 14
5801人浏览 9人回答问题 分享 举报
9 个回答

您需要登录后才可以回复 登录 | 注册