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.

[参考译文] MSP430FR5994:SoftUart

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1131323/msp430fr5994-softuart

器件型号:MSP430FR5994

很棒的下午社区!

有人已经工作过 SoftUart? 我需要帮助。 我将在 频率为8MHz 的 MSP430FR5994微控制器上实现115200Hz 的 SoftUart。 TXD  位于 P4.1、RXD 位于 P4.2。  
它已经发送了字符串、但在接收时它只接收1。  感谢你的帮助。

以下是我的代码。

// main.c ----------------------------

#include
#include
#include "UART.h"

int main (空)
{    
    //停止看门狗计时器
    WDTCTL = WDTPW + WDTHOLD;        //停止 WDT
    SetClockMHz();
    ConfigurePORTS();
    PM5CTL0 &=~LOCKLPM5;                 //禁用 GPIO 上电
    _enable_interrupt ();                         //启用全局中断

   UART_PUTs (" MSP430 SoftUart 115200\n"r);

    while (1)
    
        if (UART_getc (&Data)){
            UART_putc (数据);
            _DELAY_CYCLES (4000000);
        
    

// uart.h ----------------------------------------

#ifndef __UART_H
#define _UART_H

#include
#include

#定义 TXD BIT1                                    // TXD em P4.1
# define RXD BIT2                                   // RXD em P4.2
# define F8MHz 8000000                           // CPU 8MHz
# define BAUDRATE 115200                       // taxa de transmissão
# define BIT_TIME (F8MHz/BAUDRATE)      // Tempo de 位
# define half_bit_time (bit_time/2)        // Tempo de meio 位
静态易失性 uint8_t bitCount=0;                  // Contagem DE 位
静态无符号 int TXByte;                          // Valor envado por UART_putc ()
静态无符号 int RXByte;                          // Valor recibido
静态 bool 接收= false;                    //状态调整
静态 bool 接收器接收= false;                  // um 字节 e recibido

/*初始化软 UART */
void SetClockMHz (void);
void ConfigurePORTS (void);
bool UART_getc (uint8_t * c);
void UART_putc (uint8_t c);
void UART_puts (const char *str);

#endif /* UART_H_*/

// uart.c ----------------------------------

#include
#include
#include "UART.h"

/*初始化软 UART */
空 SetClockMHz (空)

    // DCO ~8MHz 的启动时钟系统
   CSCTL0 = CSKEY;                     //解锁 CS 寄存器
    CSCTL1 = DCOFSEL_6;                //将 DCO 设置为8MHz
    CSCTL2 = SELA_VLOCLK|SELESS__DCOCLK|SELM_DCOCLK;
    CSCTL3 = DIVA__1|DIVS_1|DIVM_1;   //设置所有分频器
    CSCTL0_H = 0;                       //锁定 CS 寄存器
    返回;

空配置 PORTS (空)

    //配置 TXD
    P4DIR |= TXD;         // P4.1 TX 输出

    //配置 RXD
    P4DIR &=~RXD;    // P4.2 RX 输入
    P4OUT |= RXD;     //设置内部上拉电阻器
    P4REN |= RXD;     //启用内部上拉电阻器
    P4IES |= RXD;      //高电平到低电平转换
    P4IFG &=~RXD;    //清除中断标志
    P4IE |= RXD;        //中断使能
    返回;

/*从 UART 非阻塞式读取一个字符。*/
bool UART_getc (uint8_t * c)

    如果(!已接收){返回 false;}
    *c = RXByte;
    接收器= false;
    返回 true;

/*将一个字符串写入 UART 阻塞*/
void UART_putc (uint8_t c)

    TXByte = c;
    while (isReceiving);                                //等待 RX 完成

    位计数= 0xA;                                   //加载位计数器,开始+ 8位+停止
    TXByte |= 0x100;                                  //向 TXByte 添加停止位
    TXByte = TXByte << 1;                           //添加起始位0

    TA0CTL = tassel_SMCLK + MC_Continous;// SMCLK/1 +连续模式
    TA0CCR0 = TA0R;                                //获取当前计时器计数
    TA0CCR0 +=位时间;                          //将偏移添加到 TA0CCR0
    TA0CCTL0 = CCIS_0 + OUTMOD_0 + CCIE + OUT;//设置信号、启用中断
    while (TA0CCTL0和 CCIE);                       //等待之前的 TX 完成
    返回;

/*将字符串写入 UART 阻塞。 *
void UART_puts (const char * str){
    if (* str!= 0) uart_putc (* str++);
    while (* str!= 0) UART_putc (* str++);
    返回;

Port4的/* ISR */
#pragma vector = Port4_vector
_interrupt void Port4_ISR (void)

    isReceiving = true;
    P4IE &=~RXD;                                //禁用中断 P4.2
    P4IFG &=~RXD;                               //清除中断标志 P4.2

    TA0CTL = tassel_SMCLK + MC__Continous;// SMCLK + Continuous Mode
    TA0CCR0 = TA0R;                            //初始化 TA0CCR0
    TA0CCR0 += HALF_BIT_TIME;              //将偏移添加到 TA0CCR0
    TA0CCTL0 = OUTMOD_1 + CCIE;          //禁用 TX 并启用中断计时器

    RXByte = 0x00;                              //初始化 RXByte
    位计数= 0x9;                               //加载位计数器,8位+ 1起始

用于   TXD 和 RXD 的/* CCR0 ISR */
#pragma vector = TIMER0_A0_vector
_interrupt void Timer0_A0_ISR (void)

    TA0CCR0 +=位时间;                    //将偏移添加到 TA0CCR0
    if (!isReceiving){                              //收发
        如果(bitCount = 0){                       //完成?
        TA0CTL = tassel__SMCLK;           // tassel_SMCLK,计时器关闭
        TA0CCTL0 &=~CCIE;                   //禁用中断计时器
        
        否则{
            IF (TXByte & 0x01){P4OUT |= TXD;} // P4.1 = 1
            否则{P4OUT &=~TXD;}             // P4.1 = 0
            TXByte >=1;
            bitCount --;
            
    
    否则{                                          //接收
        如果(bitCount = 0){                         //完成?
            TA0CTL = tassel__SMCLK;         // SMCLK,计时器关闭
            TA0CCTL0 &=~CCIE;                 //禁用中断计时器
            P4IE |= RXD;                            //中断使能 P4.2
            isReceiving = false;
            如果((RXByte & 0x201)== 0x200){     //验证起始位和停止位
                RXByte >=1;                     //删除起始位
                RXByte &= 0xFF;                   //删除停止位
                接收器= true;
            
        
        否则{
        如果(P4IN & RXD){RXByte |= 0x400;}      //如果位被置位?
            RXByte >=1;                         //向下移动位
            bitCount --;
        
    

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

    在 CCR0 ISR 中、在接收时、您使用以下命令开始下一个接收:

    P4IE |= RXD;//中断使能 P4.2

    此时、由于之前的活动、P4IFG.2几乎肯定=1、因此您将立即重新启动接收并获得接下来的所有1。

    在这一行前面、添加如下内容:

    P4IFG &=~RXD;//清除过期

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

    Bruce、您好、谢谢  

    要接收一个字节、首先处理 Port4 ISR、然后此例程激活 CCR0 ISR。
    第一个标志中已禁用此标志。  

    /*用于端口4的 ISR */...

    > P4IFG &=~RXD;//清除中断标志 P4.2

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

    但 IFG 继续触发到达字节中的每0位。 例外情况是一个1字节-- --例如你的"虚拟"字节----这就是它在第二轮之后停止发生的原因。

    你是否尝试过我的建议? 它在我这么做时起作用了。

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

    P4IE 在接收到一个完整字节前被禁用。  

    Port4的/* ISR */
    #pragma vector = Port4_vector
    _interrupt void Port4_ISR (void)

        isReceiving = true;
        P4IE &=~RXD;                              //禁用中断 P4.2
        P4IFG &=~RXD;                            //清除中断标志 P4.2

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

    通常、IFG 位被置位、与它们相应的 IE 位无关。 当 IE=0时、IFG 状态为"堆叠"是例程。 这就是为什么(通常)在设置 IFG 的 IE 之前清除 IFG 是一种良好的习惯,而不仅仅是在本例中。

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

    更改后、结果相同。  

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

    当我进行该更改时、它开始工作。 我不知道我们在做什么不同。

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

    没错、我在    CCR0 ISR 例程中清理了 IFG 、现在它可以工作了。

    Bruce、非常感谢。

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

    Bruce、 感谢您的出色帮助!