This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TM4C123GH6PM:与 HMC5883L (3轴数字指南针 IC)的 I2C 通信

Guru**** 1794070 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/572120/tm4c123gh6pm-i2c-communication-with-hmc5883l-3-axis-digital-compass-ic

器件型号:TM4C123GH6PM

大家好、

我正在尝试从 HMC5883L 读取数据。 我尝试根据 HMC5883L 数据表建立通信网络、但无法读取数据。 如果您能仔细检查我的代码并建议我如何解决问题、我将不胜感激。 提前感谢您的参与。

#include "tm4c123ghp6.h"

//全局变量
int i=0;
unsigned long 数据;

//


#define I2C_MCS-78_ACK 0x00000008 //数据确认使能
#define I2C_MCS-78_DATACK 0x00000008 //确认数据
#define I2C_MCS-78_ADRACK 0x00000004 //确认地址
#define I2C_MCS-78_STOP 0x00000004 //生成 STOP
#define I2C_MCS-78_START 0x00000002 //生成开始
#define I2C_MCS-78_ERROR 0x00000002 //错误
#define I2C_MCS-78_run 0x00000001 // I2C 主设备启用
#define I2C_MCS-78_BUSY 0x00000001 // I2C BUSY
#define I2C_MCR_MFE 0x00000010 // I2C 主机功能启用

#define MAXRETRIES 5. //放弃

void I2C0_Init (void)前的接收尝试次数{
SYSCTL_RCGCI2C_R |= 0x0001; //激活 I2C0
SYSCTL_RCGCGPIO_R |= 0x0002; //激活端口 B
while ((SYSCTL_PRGPIO_R&0x0002)=0){};//准备好了?

GPIO_PORTB_AFSEL_R |= 0x0C; // 3)在 PB2、3
GPIO_PORTB_ODR_R 上启用 alt funt |= 0x08; // 4)仅在 PB3上启用开漏
GPIO_PORTB_DEN_R |= 0x0C; // 5)在 PB2、3上启用数字 I/O
// 6)将 PB2、3配置为 I2C
GPIO_PORTB_PCTL_R =(GPIO_PORTB_PCTL_R&0xFFFF00FF)+0x00003300;
GPIO_PORTB_AMSEL_R &&~0x0C; // 7)禁用 PB2、3
I2C0_MCR_R = I2C_MCR_MFE 上的模拟功能; // 9)主功能使能
I2C0_MTPR_R = 0x07; // 8)配置为100kbps 时钟
// 16MHz*(TPR+1)*20ns => TPR=7
}

void SlaveAddress (unsigned long slaveAddress){

I2C1_MSA_R=((slaveAddress)<< 1);

}

void EndTransmission (void){
while (I2C0_MCS-78_R&I2C_R);
//等待0x1 ~ //发送的 MSA[0]为0
// I2C0_MDR_R = data1&0xFF; //准备第一个字节
I2C0_MCS-78_R =(0
//&~I2C_MCS-78_ACK //无数据应答(发送时无数据)
| I2C_MCS-78_STOP //生成停止
//| I2C_MCS-78_START //不启动/重新启动
| I2C_MCS-78_RUN);//主设备启用
while (I2C0_MCS-78_R&I2C_MCS-78忙)};//等待传输完成

}

unsigned long I2C_Send_NO_start (unsigned long data1){
while (I2C0_MCS-78_R&I2C_MCS-78_BUSY)};//等待 I2C 就绪
I2C0_MSA_R &&~0x01; //发送
I2C0_MDR_R = data1&0xFF 时、MSA[0]为0; //准备第一个字节
I2C0_MCS-78_R =(0
//&~I2C_MCS-78_ACK //无数据应答(发送时无数据)
//| I2C_MCS-78_STOP //停止
//| I2C_MCS-78_START //不启动/重新启动
| I2C_MCS-78_RUN);//主设备启用
while (I2C0_MCS-78_R&I2C_MCS-78忙){};//等待传输完成
//返回错误位
返回(I2C0_MCS-78R &(I2C_MCS-78_DATACC|I2C_MCS_ADRACK|I2C_MCS_ERROR));
}


unsigned long I2C_Send_NO_stop (unsigned long data1){
while (I2C0_MCS-78_BUS_BUSY)};//等待 I2C I2C_0_R=
0x01;~ //发送
I2C0_MDR_R = data1&0xFF 时、MSA[0]为0; //准备第一个字节
I2C0_MCS-78_R =(0
//&~I2C_MCS-78_ACK //无数据应答(发送时无数据)
//| I2C_MCS-78_STOP //生成停止
| I2C_MCS-78_START //生成启动/重新启动
| I2C_MCS-78_RUN);//主设备启用
while (I2C0_MCS-78_R&I2C_MCS-78忙){};//等待传输完成
//返回错误位
返回(I2C0_MCS-78_R&(I2C_MCS-78_DATACK_I2C_MCS-78K_I2C_MCS-78_ERROR));
}

unsigned long I2C_Recv (unsigned long slave){
int retryCounter = 1;
DO{
while (I2C0_MCS-78_R&I2C_MCS-78忙){};//等待 I2C 就绪
I2C0_MSA_R =(从器件<<1)&0xFE;// MSA[7:1]是从器件地址
I2C0_MSA_R |= 0x01; //对于接收,MSA[0]为1
I2C0_MCS-78_R =(0
//&~I2C_MCS-78_ACK //负数据 ACK (最后一个字节)
| I2C_MCS-78_STOP //生成停止
| I2C_MCS-78_START //生成启动/重新启动
| I2C_MCS-78_run);//主设备启用
while (I2C0_MCS-78_R&I2C_MCS-78忙){};//等待传输完成
RetryCounter = RetryCounter + 1; //递增重试计数
器} //
如果出错 while ((((I2C0_MCS-78_R&(I2C_MCS-78K_I2C_MCS-78K_MCS_ERROR))!= 0)&&(retryCounter <= MAXRETRIES));
return (I2C0_MDR_R&0xFF),则重复此操作; //通常在出错
时返回0xFF}


void SystemInit (void){}

int main (void){
I2C0_Init ();
Slave_Address (0x1E); //根据 HMC5883L 数据表

,从机地址为0x1E //“连续测量模式(HMC5883L)第18页的初始化过程

//(8平均值、15Hz 默认值、正常测量)
I2C_Send_NO_stop (0x3C);
I2C_Send_NO_start (0x00);
I2C_Send_NO_start (0x70);

//(gain=5、或任何其他所需的增益)
I2C_Send_NO_stop (0x3C);
I2C_Send NO_start


(0x000+);





(0x000+);I2C_Send (0x000+);(0x000+);(0x000+ I end_start);
(0x000+);(0x000+(0x000+)

//结束传输
结束();


while (1){

Slave_Address (0x1E);
I2C_Send_no_stop (0x3D);//根据 HMC5883L 数据表第2页
的 I2C 地址读取数据 I2C_Send_no_start (0x03);//地址位置03、即 X-MSB
数据= I2C_Recv (0x1E);//读取 X

}/读取 X


  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    #include "tm4c123ghp6.h"

    //全局变量
    int i=0;
    无符号长整型数据;

    //


    #define I2C_MCS-78_ACK 0x00000008 //数据确认使能
    #define I2C_MCS-78_DATACK 0x00000008 //确认数据
    #define I2C_MCS-78_ADRACK 0x00000004 //确认地址
    #define I2C_MCS-78_STOP 0x00000004 //生成停止
    #define I2C_MCS-78_START 0x00000002 //生成启动
    #define I2C_MCS-78_ERROR 0x00000002 //错误
    #define I2C_MCS-78_run 0x00000001 // I2C 主机启用
    #define I2C_MCS-78忙 0x00000001 // I2C 忙
    #define I2C_MCR_MFE 0x00000010 // I2C 主机功能启用

    #define MAXRETRIES 5. //放弃前的接收尝试次数

    void I2C0_Init (void){
    SYSCTL_RCGCI2C_R |= 0x0001; //激活 I2C0
    SYSCTL_RCGCGPIO_R |= 0x0002; //激活端口 B
    while (((SYSCTL_PRGPIO_R&0x0002)==0){};//准备好了?

    GPIO_PORTB_AFSEL_R |= 0x0C; // 3)在 PB2、3上启用 alt funt
    GPIO_PORTB_ODR_R |= 0x08; // 4)仅在 PB3上启用开漏
    GPIO_PORTB_DEN_R |= 0x0C; // 5)在 PB2、3上启用数字 I/O
    // 6)将 PB2、3配置为 I2C
    GPIO_PORTB_PCTL_R =(GPIO_PORTB_PCTL_R&0xFFFFFF)+ 0x00003300;
    GPIO_PORTB_AMSEL_R &=~0x0C; // 7)禁用 PB2、3上的模拟功能
    I2C0_MCR_R = I2C_MCR_MFE; // 9)使能主功能
    I2C0_MTPR_R = 0x07; // 8)配置为100kbps 时钟
    // 16MHz*(TPR+1)*20ns => TPR=7


    void Slave_Address (unsigned long slaveAddress){

    I2C1_MSA_R=((slaveAddress)<< 1);



    void EndTransmission (void){
    while (I2C0_MCS-78_R&I2C_MCS-78忙){};//等待 I2C 就绪
    //I2C0_MSA_R &=~0x01; //发送的 msa[0]为0
    // I2C0_MDR_R = data1&0xFF; //准备第一个字节
    I2C0_MCS-78_R =(0
    //&~I2C_MCS-78_ACK //无数据应答(发送时无数据)
    | I2C_MCS-78_STOP //生成停止
    //| I2C_MCS-78_START //不启动/重新启动
    | I2C_MCS-78_run);//主设备启用
    while (I2C0_MCS-78_R&I2C_MCS-78忙){};//等待传输完成



    unsigned long I2C_Send_NO_start (unsigned long data1){
    while (I2C0_MCS-78_R&I2C_MCS-78忙){};//等待 I2C 就绪
    I2C0_MSA_R &=~0x01; //发送的 msa[0]为0
    I2C0_MDR_R = data1&0xFF; //准备第一个字节
    I2C0_MCS-78_R =(0
    //&~I2C_MCS-78_ACK //无数据应答(发送时无数据)
    //| I2C_MCS-78_STOP //停止
    //| I2C_MCS-78_START //不启动/重新启动
    | I2C_MCS-78_run);//主设备启用
    while (I2C0_MCS-78_R&I2C_MCS-78忙){};//等待传输完成
    //返回错误位
    返回(I2C0_MCS-78_R&(I2C_MCS-78_DATAAC|I2C_MCS-78K_I2C_MCS-78_ERROR));



    unsigned long I2C_Send_NO_stop (unsigned long data1){
    while (I2C0_MCS-78_R&I2C_MCS-78忙){};//等待 I2C 就绪
    I2C0_MSA_R &=~0x01; //发送的 msa[0]为0
    I2C0_MDR_R = data1&0xFF; //准备第一个字节
    I2C0_MCS-78_R =(0
    //&~I2C_MCS-78_ACK //无数据应答(发送时无数据)
    //| I2C_MCS-78_STOP //生成停止
    | I2C_MCS-78_START //生成启动/重新启动
    | I2C_MCS-78_run);//主设备启用
    while (I2C0_MCS-78_R&I2C_MCS-78忙){};//等待传输完成
    //返回错误位
    返回(I2C0_MCS-78_R&(I2C_MCS-78_DATAAC|I2C_MCS-78K_I2C_MCS-78_ERROR));


    unsigned long I2C_Recv (unsigned long 从器件){
    Int retryCounter = 1;
    执行{
    while (I2C0_MCS-78_R&I2C_MCS-78忙){};//等待 I2C 就绪
    I2C0_MSA_R =(从器件<<1)&0xFE;// MSA[7:1]是从器件地址
    I2C0_MSA_R |= 0x01; //对于接收,MSA[0]为1
    I2C0_MCS-78_R =(0
    //&~I2C_MCS-78_ACK //负数据 ACK (最后一个字节)
    | I2C_MCS-78_STOP //生成停止
    | I2C_MCS-78_START //生成启动/重新启动
    | I2C_MCS-78_run);//主设备启用
    while (I2C0_MCS-78_R&I2C_MCS-78忙){};//等待传输完成
    RetryCounter = RetryCounter + 1; //递增重试计数器
    } //如果出现错误,则重复此操作
    while ((((I2C0_MCS-78_R&(I2C_MCS_ADRACK_I2C_MCS_ERROR))!= 0)&&(retryCounter <= MAXRETRIES));
    返回(I2C0_MDR_R&0xFF); //通常在出错时返回0xFF



    void SystemInit (void){}

    int main (void){
    I2C0_Init();
    Slave_Address (0x1E); //根据 HMC5883L 数据表、从器件地址为0x1E

    //“连续测量模式(HMC5883L)的初始化过程第18页

    //(8平均值、默认值15Hz、正常测量)
    I2C_Send_NO_STOP (0x3C);
    I2C_Send_NO_START (0x00);
    I2C_Send_NO_START (0x70);

    //(gain=5、或任何其他所需的增益)
    I2C_Send_NO_STOP (0x3C);
    I2C_Send_NO_START (0x01);
    I2C_Send_NO_START (0xA0);

    //(连续测量模式)
    I2C_Send_NO_STOP (0x3C);
    I2C_Send_NO_START (0x02);
    I2C_Send_NO_START (0x00);

    //延迟
    对于(i =0;i<100000;i++){};
    对于(i =0;i<100000;i++){};

    //结束传输
    结束传输();


    while (1){

    Slave_Address (0x1E);
    I2C_Send_NO_STOP (0x3D);//根据 HMC5883L 数据表第2页读取数据的 I2C 地址
    I2C_Send_NO_start (0x03);//地址位置03、即 X-MSB
    数据= I2C_Recv (0x1E);//读取 X-MSB



  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Ashkan、

    请避免使用 DRM 方法访问从器件。 我们不建议使用此方法、因为用于支持调试的分析很困难且容易出错。 我建议在我们能够为您提供最佳支持之前使用 TivaWare API。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Amit、您好!

    感谢你能抽出时间。 我也会尝试这样做。 有一个好的

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Ashklan、

    谢谢你。