打印
[牛人杂谈]

NUC970裸机IIC驱动

[复制链接]
709|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
gwsan|  楼主 | 2021-6-5 20:11 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
NUC970裸机IIC的驱动,使用很简单,没有DMA,效率不怎么样,跟软件IIC一样,因为需要阻塞延时等待,调试过程中遇到的问题就是一旦IIC出现异常,没有复位机制,可能会导致一次通讯异常,之后错误状态会自动清除。

//IIC.c

/*************************************************************************************************************
* 文件名:                        IIC.c
* 功能:                        NUC970 IIC驱动
* 作者:                        cp1300@139.com
* 创建时间:                2020-10-21
* 最后修改时间:        2020-10-21
* 详细:                        2020-11-03:只支持7bit地址模式
*************************************************************************************************************/
#include "nuc970_system.h"
#include "iic.h"

//IIC基址       
static const u32 scg_IICx_Base[IIC_CH_COUNT] = {IIC0_BASE, IIC1_BASE};
//IIC时钟使能       
static const SYS_DEV_CLOCK scg_IICx_DeviceClockEnable[IIC_CH_COUNT]         = {DEV_IIC0, DEV_IIC1};
//外设复位       
static const SYS_DEV_RESET scg_IICx_DeviceReset[IIC_CH_COUNT] = {        DEV_RESET_IIC0,         DEV_RESET_IIC1};       
//IO复用功能
static const GPIO_AF_Type scg_IICx_AF_GPIO[IIC_CH_COUNT][2] =
{
        {GPIO_PG1_I2C0_SDA,         GPIO_PG0_I2C0_SCL},
        {GPIO_PG3_I2C1_SDA,         GPIO_PG2_I2C1_SCL},
};

//IIC句柄
typedef struct
{
        IIC_CH_Type ch;                        //当前通道
        IIC_TypeDef *IICx;
        u32 TimeOutUs;                        //操作超时,单位us
        u16 Speed_KHz;                        //通讯速度,单位KHz
}IIC_HANDLE;

//IIC通道句柄定义
static IIC_HANDLE sg_IIC_Handle[IIC_CH_COUNT];

//IIC操作码(不能同时使能读与写)
#define IIC_OPCODE_START                (1<<4)        //发送START信号
#define IIC_OPCODE_STOP                        (1<<3)        //发送STOP信号
#define IIC_OPCODE_READ                        (1<<2)        //读取数据
#define IIC_OPCODE_WRITE                (1<<1)        //写入数据
#define IIC_OPCODE_NACK                        (1<<0)        //读数据时发送NACK

#define IIC_CSR_NACK                        (1<<11)        //NACK
#define IIC_CSR_BUSY                        (1<<10)        //总线忙
#define IIC_CSR_AL                                (1<<9)        //仲裁丢失(只读)-总线电平故障
#define IIC_CSR_TIP                                (1<<8)        //传输进行中


使用特权

评论回复
沙发
gwsan|  楼主 | 2021-6-5 20:12 | 只看该作者
/*************************************************************************************************************************
* 函数        :                        bool IIC_Init(IIC_CH_Type ch, u16 Speed_KHz, u16 TimeOutUs)
* 功能        :                        硬件IIC初始化
* 参数        :                        ch:IIC通道;Speed_KHz:速度10-1000;TimeOutUs:操作超时us(0:自动计算超时)
* 返回        :                        IIC_ERROR
* 依赖        :                        底层宏定义
* 作者        :                        cp1300@139.com
* 时间        :                        2020-11-03
* 最后修改时间 :         2020-11-03
* 说明        :                        
*************************************************************************************************************************/
bool IIC_Init(IIC_CH_Type ch, u16 Speed_KHz, u16 TimeOutUs)
{
        IIC_HANDLE *pHandle;
        u32 temp;
       
        if((u32)ch >= IIC_CH_COUNT) return FALSE;
       
        SYS_DeviceClockEnable(scg_IICx_DeviceClockEnable[ch], TRUE);        //使能时钟
        SYS_DeviceReset(scg_IICx_DeviceReset[ch]);                                                //复位外设
        //配置初始化
        pHandle = &sg_IIC_Handle[ch];                                                                        //获取相关通道的句柄
        pHandle->IICx = (IIC_TypeDef *)scg_IICx_Base[ch];                                //外设指针
        if(Speed_KHz > 1000) Speed_KHz = 1000;
        if(Speed_KHz < 1) Speed_KHz = 1;
        pHandle->Speed_KHz = Speed_KHz;                                                                        //记录速度
        if(TimeOutUs == 0)                                                                                                //需要自动计算超时时间,时钟周期*10*10
        {
                TimeOutUs = 1000/Speed_KHz;                                                                        //时钟周期
                TimeOutUs *= 10;                                                                                        //字节周期
                TimeOutUs *= 10;                                                                                        //超时时间为10个字节时间
        }
        if(TimeOutUs < 3) TimeOutUs = 3;
        pHandle->TimeOutUs = TimeOutUs;                                                                        //记录通讯超时时间
        uart_printf("IIC超时时间:%dus\r\n", pHandle->TimeOutUs);
        temp = SYS_GetPCLKSpeed()/(1000 *5 * Speed_KHz) - 1;                        //计算分频
        if(temp > 65535) temp = 65535;
        if(temp < 1) temp = 1;
        //IIC寄存器配置
        pHandle->IICx->DIVIDER = temp;                                                                        //设置分频器
        pHandle->IICx->CMDR = 0;
        pHandle->IICx->CSR = 1<<0;                                                                                //使能IIC,并且一次写入1字节       

        //IO初始化
        SYS_GPIOx_SetAF(scg_IICx_AF_GPIO[ch][0]);                                                 //SDA 复用功能设置
        SYS_GPIOx_SetAF(scg_IICx_AF_GPIO[ch][1]);                                                 //SCL 复用功能设置
       
        return TRUE;
}



使用特权

评论回复
板凳
gwsan|  楼主 | 2021-6-5 20:13 | 只看该作者
/*************************************************************************************************************************
* 函数        :                        static IIC_ERROR IIC_WaitIdle(IIC_HANDLE *pHandle)
* 功能        :                        等待IIC空闲
* 参数        :                        pHandle:句柄
* 返回        :                        IIC_ERROR
* 依赖        :                        底层宏定义
* 作者        :                        cp1300@139.com
* 时间        :                        2020-11-03
* 最后修改时间 :         2020-11-03
* 说明        :                         由于有些错误没法主动清除,而且硬件IIC也没有复位功能,无法清除某些错误,只能通过发送一个STOP信号
*************************************************************************************************************************/
static IIC_ERROR IIC_WaitIdle(IIC_HANDLE *pHandle)
{
        u16 TimeOut = 10;
       
        if(pHandle->IICx->CMDR == 0) return IIC_OK;                                                //只要没有命令在执行,则认为不忙
        if(pHandle->IICx->CSR & IIC_CSR_BUSY)                                                        //忙
        {
                pHandle->IICx->CMDR = IIC_OPCODE_STOP;                                                //发送STOP信号,结束上一次通讯
        }
       
        //等待空闲
        while((pHandle->IICx->CSR & IIC_CSR_BUSY) && TimeOut)                        //忙
        {
                SYS_DelayMS(1);
                TimeOut --;
        }
       
        if(pHandle->IICx->CSR & IIC_CSR_BUSY)                                                        //忙
        {
                DEBUG("IIC错误:总线忙\r\n");
                return IIC_BUSY;
        }
        else return IIC_OK;       
}



使用特权

评论回复
地板
gwsan|  楼主 | 2021-6-5 20:13 | 只看该作者
/*************************************************************************************************************************
* 函数        :                        static __inline IIC_ERROR IIC_WaitTransComplete(IIC_HANDLE *pHandle)
* 功能        :                        等待数据发送完成
* 参数        :                        pHandle:句柄
* 返回        :                        IIC_ERROR
* 依赖        :                        底层宏定义
* 作者        :                        cp1300@139.com
* 时间        :                        2020-11-03
* 最后修改时间 :         2020-11-03
* 说明        :                         发送的时候有时候NACK会有效,但是发送命令之后才会清除,因此必须在发送完或超时后才去检测NACK信号
*************************************************************************************************************************/
static __inline IIC_ERROR IIC_WaitTransComplete(IIC_HANDLE *pHandle)
{
        u16 TimeOut = pHandle->TimeOutUs;
       
        while(1)
        {
                Delay_US(1);
                if((pHandle->IICx->CSR & IIC_CSR_TIP) == 0) break;                        //传输完成
                //等待超时
                TimeOut --;
                if(TimeOut ==0) break;
        }

        if((pHandle->IICx->CSR & IIC_CSR_TIP) == 0)
        {
                if(pHandle->IICx->CMDR & IIC_OPCODE_WRITE) return IIC_HAL_ERROR;                                //如果此时命令依旧有效,肯定发生了底层硬件异常
                else return IIC_OK;
        }               
        else if(pHandle->IICx->CSR & IIC_CSR_NACK)
        {
                return IIC_NACK;
        }       
        else return IIC_TIMEOUT;
}



使用特权

评论回复
5
gwsan|  楼主 | 2021-6-5 20:14 | 只看该作者

/*************************************************************************************************************************
* 函数        :                        static __inline IIC_ERROR IIC_SendByte(IIC_HANDLE *pHandle, u8 data, u8 cmd)
* 功能        :                        发送一字节,并等待传输结果
* 参数        :                        pHandle:句柄;data:要发送的一字节数据;cmd:命令
* 返回        :                        IIC_ERROR
* 依赖        :                        底层宏定义
* 作者        :                        cp1300@139.com
* 时间        :                        2020-11-03
* 最后修改时间 :         2020-11-03
* 说明        :                        
*************************************************************************************************************************/
static __inline IIC_ERROR IIC_SendByte(IIC_HANDLE *pHandle, u8 data, u8 cmd)
{
        pHandle->IICx->TXD = data;                                                        //地址
        pHandle->IICx->CMDR = cmd;                                                        //发送命令
        return IIC_WaitTransComplete(pHandle);                                //等待传输完成
}



使用特权

评论回复
6
gwsan|  楼主 | 2021-6-5 20:15 | 只看该作者
今天看到有人在问SPI flash读取数据的方法,为什么这样读取?

先给出一个函数,SPI的读取函数:

/*!
    \brief      read a block of data from the flash
    \param[in]  pbuffer: pointer to the buffer that receives the data read from the flash
    \param[in]  read_addr: flash's internal address to read from
    \param[in]  num_byte_to_read: number of bytes to read from the flash
    \param[out] none
    \retval     none
*/
spiflash_ret spiflash_buffer_read(uint8_t* pbuffer, uint32_t read_addr, uint16_t num_byte_to_read)
{
    spiflash_ret ret = spiflash_ret_success;
    /* select the flash: chip slect low */
    SPI_FLASH_CS_LOW();

    /* send "read from memory " instruction */
    spi_flash_send_byte(READ);

    /* send read_addr high nibble address byte to read from */
    spi_flash_send_byte((read_addr & 0xFF0000) >> 16);
    /* send read_addr medium nibble address byte to read from */
    spi_flash_send_byte((read_addr& 0xFF00) >> 8);
    /* send read_addr low nibble address byte to read from */
    spi_flash_send_byte(read_addr & 0xFF);

    /* while there is data to be read */
    while(num_byte_to_read--){
        /* read a byte from the flash */
        *pbuffer = spi_flash_send_byte(DUMMY_BYTE);
        /* point to the next location where the byte read will be saved */
        pbuffer++;
    }

    /* deselect the flash: chip select high */
    SPI_FLASH_CS_HIGH();

    return ret;
}
函数的参数就不再说了,有注释看下就可以。一个是返回的数据地址,一个是即将读取的地址,这里应该通俗一点说,要读取flash上哪个位置,最后一个是读取的字节数!


使用特权

评论回复
7
gwsan|  楼主 | 2021-6-5 20:16 | 只看该作者
/*************************************************************************************************************************
* 函数        :                        static __inline IIC_ERROR IIC_WaitReadComplete(IIC_HANDLE *pHandle)
* 功能        :                        等待数据接收完成
* 参数        :                        pHandle:句柄;
* 返回        :                        IIC_ERROR
* 依赖        :                        底层宏定义
* 作者        :                        cp1300@139.com
* 时间        :                        2020-11-03
* 最后修改时间 :         2020-11-03
* 说明        :                        
*************************************************************************************************************************/
static __inline IIC_ERROR IIC_WaitReadComplete(IIC_HANDLE *pHandle)
{
        u16 TimeOut = pHandle->TimeOutUs;
       
        while(1)
        {
                Delay_US(1);
                if((pHandle->IICx->CSR & IIC_CSR_TIP) == 0) break;                        //传输完成
                //等待超时
                TimeOut --;
                if(TimeOut ==0) break;
        }

        if((pHandle->IICx->CSR & IIC_CSR_TIP) == 0)
        {
                if(pHandle->IICx->CMDR & IIC_OPCODE_READ)
                {
                        //uart_printf("pHandle->IICx->CMDR=0x%X\r\n", pHandle->IICx->CMDR);
                        return IIC_HAL_ERROR;                                //如果此时命令依旧有效,肯定发生了底层硬件异常
                }
                else return IIC_OK;
        }               
        else return IIC_TIMEOUT;
}



使用特权

评论回复
8
gwsan|  楼主 | 2021-6-5 20:17 | 只看该作者
/*************************************************************************************************************************
* 函数        :                        static __inline IIC_ERROR IIC_ReadByte(IIC_HANDLE *pHandle, u8 *data, bool isEndRead)
* 功能        :                        接收一字节,并返回状态
* 参数        :                        pHandle:句柄;data:返回的数据;isEndRead:是否是最后一次读取
* 返回        :                        IIC_ERROR
* 依赖        :                        底层宏定义
* 作者        :                        cp1300@139.com
* 时间        :                        2020-11-03
* 最后修改时间 :         2020-11-03
* 说明        :                        
*************************************************************************************************************************/
static __inline IIC_ERROR IIC_ReadByte(IIC_HANDLE *pHandle, u8 *data, bool isEndRead)
{
        IIC_ERROR Error;
       
        if(TRUE == isEndRead)
        {
                pHandle->IICx->CMDR = IIC_OPCODE_READ | IIC_OPCODE_STOP | IIC_OPCODE_NACK;        //发送读取命令+NACK+STOP
        }
        else
        {
                pHandle->IICx->CMDR = IIC_OPCODE_READ;                                                //发送读取命令+ACK
        }
        Error = IIC_WaitReadComplete(pHandle);                                                        //等待接收完成
        if(Error == IIC_OK)
        {
                *data = pHandle->IICx->RXD;                                                                        //读取的数据
        }
       
        return Error;
}



使用特权

评论回复
9
gwsan|  楼主 | 2021-6-5 20:18 | 只看该作者
/*************************************************************************************************************************
* 函数        :                        IIC_ERROR IIC_MasterReadReg(IIC_CH_Type ch, u16 SlaveAddr, u16 RegAddr, bool is8bitRegAddr,
                                                u8 *pDataBuff, u16 ReadByteNum)
* 功能        :                        IIC读取寄存器(可以读取1个或者多个寄存器)
* 参数        :                        ch:IIC通道,见IIC_CH_Type;SlaveAddr:从机地址;RegAddr:要读取的寄存器地址;is8bitRegAddr:TRUE:8BIT寄存器地址,FALSE:16bit寄存器地址;
                                                pDataBuff:接收的字节数据缓冲区;ReadByteNum:要读取的寄存器数量;
* 返回        :                        IIC_ERROR
* 依赖        :                        底层宏定义
* 作者        :                        cp1300@139.com
* 时间        :                        2020-11-03
* 最后修改时间 :         2020-11-03
* 说明        :                         读取的数据都是小端模式,如果是16bit的寄存器,请读取偶数个数据,并且需要另外进行高低字节对调最后组成16bit数据
                                        可能的意外:比如一个异常的操作可能会导致IIC一直忙,此处检测到忙后会直接复位IIC,但是必须在应用层做好重入保护,比如
                                                增加信号量
                                        通过测试发现:在函数进入的时候,清除掉中断状态,之后几乎检测不到IIC忙的情况,当然在结束的时候如果检测到忙会主动发送一个STOP,在
                                                操作失败的情况下,会对IIC进行软复位,确保本次的错误不会影响下一次的IIC操作。
*************************************************************************************************************************/
IIC_ERROR IIC_MasterReadReg(IIC_CH_Type ch, u16 SlaveAddr, u16 RegAddr, bool is8bitRegAddr, u8 *pDataBuff, u16 ReadByteNum)
{
        IIC_ERROR Error = IIC_OK;
        IIC_HANDLE *pHandle;
        u16 i;
       
        if(ch > (IIC_CH_COUNT-1) || pDataBuff == NULL || ReadByteNum == 0)
        {
                DEBUG("IIC错误:无效的参数\r\n");
                return IIC_PARAMETER_ERROR;
        }
        pHandle = &sg_IIC_Handle[ch];                                        //获取相关通道的句柄
       
        Error = IIC_WaitIdle(pHandle);                                        //等待总线空闲
        if(Error != IIC_OK)                                                                //忙
        {
                DEBUG("IIC错误:总线忙,复位后未恢复\r\n");
                Error = IIC_BUSY;
                goto end_loop;
        }
       
        //发送地址以及写
        Error = IIC_SendByte(pHandle, SlaveAddr, IIC_OPCODE_START|IIC_OPCODE_WRITE);//发送写信息与开始信号,从机地址最低位为0,代表写
        if(IIC_OK != Error) goto end_loop;
        //发送寄存器地址
        if(is8bitRegAddr == FALSE)        //16bit寄存器地址,先发送高位
        {
                Error = IIC_SendByte(pHandle, RegAddr>>8, IIC_OPCODE_WRITE);                        //寄存器地址高位
                if(IIC_OK != Error) goto end_loop;
        }
        Error = IIC_SendByte(pHandle, RegAddr, IIC_OPCODE_WRITE);                                        //寄存器地址低位
        if(IIC_OK != Error) goto end_loop;
        //发送从机地址及读信号
        Error = IIC_SendByte(pHandle, SlaveAddr|BIT0, IIC_OPCODE_START|IIC_OPCODE_WRITE);                        //发送写信息与开始信号,从机地址最低位为1,代表读取
        if(IIC_OK != Error) goto end_loop;
        //循环读取数据
        for(i = 0;i < ReadByteNum;i ++)
        {
                Error = IIC_ReadByte(pHandle, &pDataBuff, (i == (ReadByteNum-1))?TRUE:FALSE);                //读取一字节
                if(IIC_OK != Error) goto end_loop;
        }
end_loop:
        //发送结束信号
        if(IIC_OK != Error)
        {
                pHandle->IICx->CMDR = IIC_OPCODE_STOP;                                                                        //发送STOP信号,结束通讯
                IIC_WaitTransComplete(pHandle);                                                                                        //等待空闲
        }

        return Error;
}



使用特权

评论回复
10
gwsan|  楼主 | 2021-6-5 20:19 | 只看该作者
//IIC.h

/*************************************************************************************************************
* 文件名:                        IIC.h
* 功能:                        NUC970 IIC驱动
* 作者:                        cp1300@139.com
* 创建时间:                2020-10-21
* 最后修改时间:        2020-10-21
* 详细:                       
*************************************************************************************************************/
#ifndef _IIC_H_  
#define _IIC_H_
#include "nuc970_system.h"

//IIC硬件接口选择
typedef enum
{
        IIC_CH0        =                0,        //IIC0
        IIC_CH1        =                1,        //IIC1
}IIC_CH_Type;
#define IIC_CH_COUNT        2        //2个IIC

//通讯错误状态
typedef enum
{
        IIC_OK                                        =        0,        //没有错误
        IIC_PARAMETER_ERROR                =        1,        //参数错误
        IIC_TIMEOUT                                =        2,        //超时错误,也可能是底层错误
        IIC_HAL_ERROR                        =        3,        //底层错误
        IIC_STOP_ERROR                        =        4,        //等待结束错误
        IIC_BUSY                                =        5,        //硬件忙
        IIC_NACK                                =        6,        //收到NACK了
}IIC_ERROR;

bool IIC_Init(IIC_CH_Type ch, u16 Speed_KHz, u16 TimeOutUs);                                                                                                                                        //IIC初始化
IIC_ERROR IIC_MasterWriteReg(IIC_CH_Type ch, u16 SlaveAddr, u16 RegAddr, bool is8bitRegAddr, u8 *pDataBuff, u16 WriteByteNum);        //IIC写寄存器(可以写1个或者多个寄存器)
IIC_ERROR IIC_MasterReadReg(IIC_CH_Type ch, u16 SlaveAddr, u16 RegAddr, bool is8bitRegAddr, u8 *pDataBuff, u16 ReadByteNum);        //IIC读取寄存器(可以读取1个或者多个寄存器)

#endif //_IIC_H_



使用特权

评论回复
11
gwsan|  楼主 | 2021-6-5 20:20 | 只看该作者
//测试代码

#include "typedef.h"
#include "nuc970_system.h"
#include "stdlib.h"
#include "main.h"
#include "test.h"
#include "QMC5883L.h"
#include "SoftwareIIC.h"
#include "iic.h"



SIIC_HANDLE g_IIC_Handle;
QMC5883L_HANDLE g_QMC5883L_Handle;
#define QMC5883L_IIC_CH                IIC_CH0


#define IS_TEST_HARDWAVE_IIC                1                //是否测试硬件IIC

//IIC读取寄存器接口
bool QMC5883L_IIC_ReadReg(u8 SlaveAddr, u8 RegAddr, u8 *pDataBuff, u16 ByteNum)               
{
#if(IS_TEST_HARDWAVE_IIC)        //测试硬件IIC
        IIC_ERROR Error;
       
        Error = IIC_MasterReadReg(QMC5883L_IIC_CH, SlaveAddr, RegAddr, TRUE, pDataBuff, ByteNum);        //IIC读取寄存器(可以读取1个或者多个寄存器)
        if(Error != IIC_OK)
        {
                uart_printf("[硬件IIC]R错误:%d\r\n", Error);
               
                return FALSE;
        }
        else return TRUE;
#else //软件IIC
        return SIIC_ReadReg(&g_IIC_Handle, SlaveAddr, RegAddr, TRUE, pDataBuff, ByteNum);        //软件IIC读取寄存器(可以读取1个或者多个寄存器)
#endif //IS_TEST_HARDWAVE_IIC
}

//IIC写入寄存器接口
bool QMC5883L_IIC_WriteReg(u16 SlaveAddr, u8 RegAddr, u8 *pDataBuff, u16 ByteNum)
{
#if(IS_TEST_HARDWAVE_IIC)        //测试硬件IIC
        IIC_ERROR Error;
       
        Error = IIC_MasterWriteReg(QMC5883L_IIC_CH, SlaveAddr, RegAddr, TRUE, pDataBuff, ByteNum);        //IIC写寄存器(可以写1个或者多个寄存器)
        if(Error != IIC_OK)
        {
                uart_printf("[硬件IIC]W错误:%d\r\n", Error);
               
                return FALSE;
        }
        else return TRUE;
#else //软件IIC
        return SIIC_WriteReg(&g_IIC_Handle, SlaveAddr, RegAddr, TRUE, pDataBuff, ByteNum);        //软件IIC写寄存器(可以写1个或者多个寄存器)
#endif //IS_TEST_HARDWAVE_IIC       
       
}


//QMC5883L0测试
void qmc5883l_test(void)
{
        s16 Temp;
        s16 MagneticData[3];

#if(IS_TEST_HARDWAVE_IIC)        //测试硬件IIC
        IIC_Init(QMC5883L_IIC_CH, 100, 0);                                                                                                                                                //硬件IIC初始化
#else //软件IIC
        SIIC_Init(&g_IIC_Handle, GPIOG, GPIOG, 1, 0, 10);                                                                                                                //软件IIC初始化
#endif //IS_TEST_HARDWAVE_IIC       
       
       
        while(QMC5883L_Init(&g_QMC5883L_Handle, 0x1A, QMC5883L_IIC_ReadReg, QMC5883L_IIC_WriteReg) == FALSE)        //QMC5883L初始化
        {
                Sleep(1000);
        }

        while(1)
        {
                if(QMC5883L_GetTemper(&g_QMC5883L_Handle, &Temp) == TRUE)                        //MPU6050读取温度
                {
                        uart_printf("[QMC5883L]温度:%s%d.%02d℃\r\n",(Temp<0)?"-":"", abs(Temp)/100, abs(Temp)%100);
                }
                else
                {
                        uart_printf("[QMC5883L]温度:ERROR\r\n");
                }
               
                if(QMC5883L_GetMagneticData(&g_QMC5883L_Handle,  &MagneticData[0], &MagneticData[1] , &MagneticData[2]) == TRUE)        //QMC5883L读取磁力计原始数据
                {
                        uart_printf("[QMC5883L]磁力计:%d %d %d\r\n", MagneticData[0],MagneticData[1],MagneticData[2]);
                }
                else
                {
                        uart_printf("[QMC5883L]磁力计:ERROR\r\n");
                }
                Sleep(500);
        }       
}


使用特权

评论回复
12
gwsan|  楼主 | 2021-6-5 20:21 | 只看该作者

//测试结果,中间故意拔掉传感器后能自动恢复


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

68

主题

3427

帖子

1

粉丝