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:MCP3008 I2C 通信、GPIO、TM4C123

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/792748/tm4c123gh6pm-mcp23008-i2c-communication-gpio-tm4c123

器件型号:TM4C123GH6PM
主题中讨论的其他器件:TM4C123

您好、社区

我尝试使用 TM4C123运行 MCP3008 I2C I/O 扩展器。 我只是从视频中复制了代码:

TM4C123教程:I2C 通信(https://www.youtube.com/watch?v=A7PUM9wPUAw

/**
*@作者 Carlos Alvarez (2015年2月26



日)**@详细信息在 Tiva-C 或 Stellaris Launchpad 板中使用 I2C 外设*驱动输入输出扩展器以控制连接到*其 GPIO 端口的8个 LED 的状态。
*
* 有关详细教程、请访问 :www.youtube.com/watch
*/
#include 
//#include 
#include 
#include 
#include "driverlib/timer.h"
#include "driverlib/sysctl.h"
#include "driverlib/interrupts.h"
#include "driverlib/gpio.h"
//#include "inc/hw_memmap.h"
#include "inc/hw_ints.h"
//I2C communication

uint8_t dLEDs = 0xuint8



/ iintu_uinth;包含8个空位/iintueAddress (inuint8);iint8 uintuintuintu.h 和 iintuintuintu.h 个 iintu.h 个空位;iintu.h 7个地址位和1个接收/发送位、用于确定下一个操作是接收(1)还是发送(0)
//slaveAddress = 0b _001.0000
I2C1->MSA =(slaveAddress<1);//指定主
器件的从器件地址}

void setRW (uint8_t 模式)
{
//如果下一个操作
是发送模式= 0、则下一个操作

I2C1->MSA &=~(1<0);//清除位,传输数据
}
否则
{
I2C1->MSA |=(1<0);//设置位、接收数据
}


void writeByte (uint8_t dataByte、uint8_t 条件)
{
//此字节包含事务期间传输的数据
I2C1->MDR = dataByte;
I2C1->MCS =条件;

while ((I2C1->MCS &(1<0)!= 0);

if ((I2C1->MCS &(1<1)!= 0)
{
if (((I2C1->MCS &(1<<4))=1){}
其他
{
I2C1->MCS =(1<<2);
while ((I2C1->MCS &(1<0)!= 0);
}
}


int main()
{//Step

1//Enalbe
并在运行模式下为 I2C 模块1提供时钟。
SYSCTl->RCGCI2C =(1<1);//使用 I2C 模块1
//步骤2
SYSCTl->RCGCGPIO =(1<0);//模块1使用端口 A =>我们必须启用端口 A 上的时钟

//Step 3
GPIOA->AFSEL =(1<<6)|(1<<7);//为引脚6和7
启用备用功能 GPIOA->DEN =(1<<6)|(1<<7);//它们是数字信号

//Step 4
//将该寄存
器中的位置位将启用相应 GPIO 管脚的开漏配置//启用该位时,该位也应在 GPIODEN 寄存器中置位。
//PA7对应于 SDA。
GPIOA->ODR =(1<<7);

//Step 5
//GPIOA->PCTL &=~0xFF000000;//this line is not required
//指定要使用的备用功能,请参阅表21-5
GPIOA->PCTL =(3<<28)|(3<24);//在 PMC7和 PMC6中分别放置3 (分别为 P7和 PA6引脚)

//Step 6
//Initialize I2C as a Master
I2C1->MCR =(1<<4);//启用主模式
//Step 7
//设置所需的 SCL 时钟速度100 Kbps
//使用第972
I2C1->MTPR = 0x7页的公式可以找到 TPR (对于我们是7);


必须发送// 1字节
setSlaveAddress (0x20);//最后7位(7-1)
setRW (0);//第一位(0)

//writeByte (字节1、字节2)

//发送 IODIR 寄存器地址
writeByte (0x00、(1<0)|(1<<1));//字节2:条件=运行和启动
//发送 IODIR 值使 GPIO 引脚输出
为 writeByte (0x00、(1<0)|(1<<2));//BTYE 2:条件=运行、停止

while (1)
{
writeByte (0x09、(1<0)|(1<1));
writeByte (0xFF、(1<0)|(1<2));

for (int i = 0;i < 1000000;i++){};
uiPeriod=SysCtlClockGet ();
}


返回0;
} 

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

    更新:它最终可以工作,但解决方案不是很专业。

    我在"run-start"和"run-stop""write Byte"函数之间添加了一个计数器、在我的情况下、这两个调用之间至少需要18个时间步长。 因此、基本上我需要在两个调用之间暂停18/16MHz = 1.0625ns。 我想知道为什么这是必要的、因为在"writeBye"函数中、我检查 I2CMCS 寄存器的"error"和"busy"、我认为这就足够了。

    但是、在这里、有人在写入 I2C 时曾经遇到过同样的问题-我是否也必须检查另一个寄存器? MCP23008是否"太慢"?

    我想去掉这个新计数器。




    writeByte (0x00、(1<0)|(1<1));//字节2:条件=运行和启动 //发送 IODIR 值以使 GPIO 引脚输出 (int i = 0;i < 18;i++){}; //此行已添加!!! writeByte (0x00、(1<0)|(1<2));//BTYE 2:conditions = run、stop while (1) { writeByte (0x09、(1<0)|(1<1)); for (int i = 0;i < 18;i++){};//此行已添加!!! writeByte (LEDs++、(1<0)|(1<2)); for (int i = 0;i < 1000000;i++){}; uiPeriod=SysCtlClockGet ();

    此致、

    标记

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

    我们感谢发布 TM4C 器件成功使用视频的用户、但我们不建议使用直接寄存器写入方法。 虽然 AllAboutEE 海报在解释每个寄存器写入方面做得很好、但我们发现大多数初始用户使用 TivaWare 函数库的方法更成功。 这些库例程会提取硬件、因此无需了解所有寄存器详细信息、然而、由于提供了源代码、用户可以查看代码并确切了解正在写入的寄存器以及如何写入。 我同意计时延迟是"kluge"、不需要、但我不能评论 Microchip 器件的性能。 根据优化级别和变量"i"的声明、优化器可以完全消除该软件延迟循环。 如果合适的 I2C 从设备没有为下一条命令做好准备、则它应该能够延长时钟周期。