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.

[参考译文] MSP430FR5729:在 MSP430FR5729上实现 MCP23S08 8位端口扩展器时出现问题

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/758000/msp430fr5729-problems-with-implementing-mcp23s08-8-bit-port-expander-on-msp430fr5729

器件型号:MSP430FR5729

您好!

我使用 的是 具有串行接口的 MCP23S08 8位 I/O 扩展器。

我想用 SPI Microchip "MCP23S08"刷写 LED。

 我的 C 代码:

#include 

#define MCP_IODIR 0x00
#define MCP_IPOL 0x01
#define MCP_GPINTEN 0x02
#define MCP_DEFVAL 0x03
#define MCP_INTMCP 0x04
#define MCP_IOMCP 0x05
#define MCP_GPPU 0x06
#define MCP_INTF 0x07
#define MCP_INTCCON AP 0x08 #define
MCP_GPIO_0x09
#define ORAT_COOLT 代码#define 0#define #define #define #define #define #define
0x40 //0100A2A1 (01000000)

void SPI_init (void); //初始化 SPI 通信
void SPI_SEND (UChar 数据); //发送 SPI 命令
void Timing_init (void);

int main (void)
{
WDTCTL = WDTPW + WDTHOLD;//停止看门狗计时器

timing_init(); //设置定时

spi_init(); //初始化 SPI 模块 UCA1

while (1)
{
P3OUT &=~BIT2;// CS 设置为低电平
_DELAY_CYCLES (200);
while ((UCA1IFG & UCTXIFG)==0);
SPI_SEND (MCP_IODIR);//初始化 IODIR
P3OUT |= BIT2;// CS 设置为高电平
_DELAY_CYCLES (200);


P3OUT &=~BIT2;// CS 设置为低电平
_DELAY_CYCLES (200);
while ((UCA1IFG & UCTXIFG)==0);
SPI_SEND (操作码);//初始化操作码
P3OUT |= BIT2;// CS 设置为高电平
_DELAY_CYCLES (200);


P3OUT &=~BIT2;// CS 设置为低电平
_DELAY_CYCLES (200);
while ((UCA1IFG & UCTXIFG)==0);
SPI_SEND (MCP_IODIR);//初始化 MCP_IODIR
P3OUT |= BIT2;// CS 设置为高电平
_DELAY_CYCLES (200);


P3OUT &=~BIT2;// CS 设置为低电平
_DELAY_CYCLES (200);
while ((UCA1IFG & UCTXIFG)==0);
SPI_SEND (0x00);//初始化0x00 LED0
P3OUT |= BIT2;// CS 设置为高电平
_DELAY_CYCLES (200);

}
}

void SPI_init (void)
{
P2SEL1 |= BIT4; //选择 P2.4的辅助功能(UCA1CLK)
P2SEL1 |= BIT5; //选择 P2.5的辅助功能(UCA1SIMO)
P2SEL1 |= BIT6; //选择 P2.6的辅助功能(UCA1SOMI)

P3DIR |= BIT2; //声明 P3.2为 Select Slave port
P3OUT |= BIT2; //从 Select Slave P3.2以高电平开始

UCA1CTLW0 |= UCCKPH; //选择时钟相位到上升时钟相位
UCA1CTLW0 |= UCMSB; //移位寄存器的方向
UCA1CTLW0 |= UCMST; // SPI 主设备
UCA1CTLW0 |= UCSYNC; //同步模式使能
UCA1CTLW0 |= UCSSEL_2; //选择 SMCLK 时钟
UCA1CTLW0 |= UCSWRST; //软件复位使能。 必须在此处进行选择

UCA1CTL1 ^= UCSWRST; //软件复位禁用。 通过这种方式设置 UCSWRST = 0
}

void SPI_send (UChar data)
{
// P3OUT &=~BIT2; //选择将 P3.2设置为低电平的从器件

UCA1TXBUF =数据; //发送数据

// P3OUT |= BIT2; //结束选择从器件并将 P3.2设置为高
电平}

void Timing_init (void)
{
//设置时钟系统
CSCTL0 = CSKEY; //启用时钟系统
CSCTL1 = DCOFSEL_3; //频率= 8、0MHz
CSCTL2 = SELA_XT1CLK | SELESS__DCOCLK | SELM_DCOCLK;//选择时钟源
CSCTL3 = DIVA__8 | DIVS__32 | DIVM__8; //设置分频器
CSCTL4 = XT2OFF | XTS | XT1DRIVE_0; // XT2被禁用、XT1:HF 模式、低功耗、无旁路
CSCTL0_H = 0; //禁用时钟系统
}

是否有人告诉我我我出了问题、或者告诉我可能忘记了什么。

我尝试学习数据表、但让该芯片正常工作并不方便。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    当我阅读数据表(219E)第1.3.3.1节时、寄存器写入操作在/CS 转换之间占用3个字节:(a)地址/方向字节(0x00表示写入)、(b)寄存器地址(IODIR)、(c)值(操作码)。

    如果您稍后决定要读取寄存器、地址/方向字节(上面的(a))将为0x01、对于(c)、您需要写入一个"虚拟"字节并捕获 RXBUF 结果。

    遗憾的是、它们没有更好的 SPI 模式图、但它与 I2C 序列相似(至少相似)。
    ----------
    > UCA1CTLW0 |= UCSWRST; //软件复位使能。 必须在此处进行选择

    这应该在初始化序列的开始而不是在末尾完成 当 UCSWRST=0时、某些字段不可设置。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    感谢您的回答。
    我已经落实了您的建议。
    您知道 LED 为什么不亮、或者为什么我没有收到信号吗?
    我是否忘记了其他什么?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    它现在有什么作用? 您的代码是什么样的?

    我希望看到它将 IODIR 寄存器(0x00)设置一次[0x40、0x00、0x40]。 (IODIR 看起来最初为0xFF [根据表1-3]、因此甚至可能不需要。)

    然后、您可以交替将 GPIO 寄存器(0x09)设置为0x40、然后将0x00设置为[0x40、0x09、0x40]和[0x40、0x09、0x00]。 确保在设置之间插入足够的延迟(可能是半秒)、以便您可以看到它发生了变化。

    每个交易(在上文"[]"内)都应放在方括号内,降低然后提高 CS。

    --------------------------

    如果您将其中的一些序列封装到函数中、则可以让您的生活更轻松、其中一个序列用于交换字节、另一个序列用于执行完整的事务(使用第一个函数3次)。

    这是一个我不断发现自己在写作的函数。 它在 SPI 上交换一个字节。 (如果您仅在传输、则可以丢弃函数结果。)

    uint8_t spix (uint8_t c)
    {
    while (!(UCA1IFG & UCTXIFG))/* empty*/;
    UCA1TXBUF = c;
    while (!(UCA1IFG & UCRXIFG)))/* empty*/;
    c = UCA1RXBUF;
    return (c)
    

    [编辑:我刚刚注意到(图1-5)写入的地址字节应为0x40、而不是0x00。 我想 这就是操作码应该是什么?]

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

    测试

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

    我没有您的设备、因此我只能从数据表中工作。

    我想您需要一个函数在器件中写入寄存器、如下所示:

    void set_reg (uint8_t reg、uint8_t value)
    {
    P3OUT &=~BIT2;// CS 低电平
    spix (0x40); //地址字节 RW=0 [参考数据表(21919E)图1-5]
    spix(reg); //注册以设置
    spix (value); //值将其设置为
    P3OUT |= BIT2;// CS 高电平
    返回;
    } 

    然后将其称为:

    SET_reg (GPIO、0x40);
    // SET_reg (GPIO、0x00)上的引脚6上的 LED;//引脚6上的 LED 关闭