【问题标题】:How can I create a bidirectional bus using a 18F4550?如何使用 18F4550 创建双向总线?
【发布时间】:2021-04-17 21:35:39
【问题描述】:

基本上,我试图将 PIC18F4550 的单个端口用作输入和输出。我打算将 7 段显示器连接到端口的 7 个引脚和同一端口的 4 个引脚。四个输入用于引入从 0 到 15 (F) 的二进制数字,二进制数字将在显示屏上以十进制表示。我使用 PIC C 编译器编译代码。

更新: 在第一条评论之后我修改了代码,我认为它基本上是一样的,我只是直接读取端口 B 的输入并使用 switch-case 来发送对应的十进制数,我还添加了一个默认状态,所以当我连接时它应该是显示中的 0。这是连接图,我的老师告诉我我可以忽略逻辑门,但我不太确定,如果我想添加我只需要使用另一个端口,如端口 D 发送单个高电平或低电平取决于端口 B 的工作方式。

更新 2: 终于成功了,似乎我可以忽略逻辑门这一事实部分正确,但代码比我更容易,我只是添加了一个三端口 D 高以及 74Ls244 和 74HC573 相应输入的 EN 和 OE 的低输出,因此我可以根据端口 B 状态(输出或输入)启用或禁用。谢谢你们。

#include<18F4550.h>
#fuses XT, NOWDT, NOLVP, NOPROTECT, PUT
#use delay(clock = 4M, crystal = 8M)
#use fast_io(b)

void main(){

int8 INDSP;
int8 OUTDSP;


while(true){

  SET_TRIS_B(0xFF);
  INDSP = input_b()&0x0F;
  switch(INDSP){
     
     case 0b00000000:
        OUTDSP = 0x3F;
     break;
     
     case 0b00000001:
        OUTDSP = 0x0C;
     break;
     
     case 0b00000010:
        OUTDSP = 0x76;
     break;
     
     case 0b00000011:
        OUTDSP = 0x5E;
     break;
     
     case 0b00000100:
        OUTDSP = 0x4D;
     break;
     
     case 0b00000101:
        OUTDSP = 0x5B;
     break;
     
     case 0b00000110:
        OUTDSP = 0x7B;
     break;
     
     case 0b00000111:
        OUTDSP = 0x0E;
     break;
     
     case 0b00001000:
        OUTDSP = 0x7F;
     break;
     
     case 0b00001001:
        OUTDSP = 0x4F;
     break;
     
     case 0b00001010:
        OUTDSP = 0x6F;
     break;
     
     case 0b00001011:
        OUTDSP = 0x79;
     break;
     
     case 0b00001100:
        OUTDSP = 0x33;
     break;
     
     case 0b00001101:
        OUTDSP = 0x7C;
     break;
     
     case 0b00001110:
        OUTDSP = 0x73;
     break;
     
     case 0b00001111:
        OUTDSP = 0x63;
     break;
     
     DEFAULT:
        OUTDSP = 0x3F;
     break;
  }
     delay_ms(500);
     SET_TRIS_B(0x00);
     output_b(OUTDSP);
     delay_ms(500);
  }
}

【问题讨论】:

  • 请提供连接图/原理图。

标签: c microcontroller pic


【解决方案1】:

警告:不是一个完整的解决方案,而是一些建议......

我们可以简化您的main,因为它有大量的重复代码:

void
main()
{

    SET_TRIS_B(0b00001111);
    DSPIN = input_b();

    while (true) {
        if ((DSPIN >= 0b00000000) && (DSPIN <= 0b00001111))
            DSPOUT = DSPIN;
        else
            DSPOUT = 0;

        delay_ms(1000);
        SET_TRIS_B(0b11111111);

        if ((DSPOUT >= 0) && (DSPOUT <= 15))
            output_b(DSPVALOR[DSPOUT]);
        else
            output_b(DSPVALOR[0]);

        delay_ms(1000);
    }
}

现在,给定main 的顶部:

SET_TRIS_B(0b00001111);
DSPIN = input_b();

我的问题是:这应该是顶部的while循环吗???

否则,不需要循环,因为DSPINDSPOUT 将保持不变。


更新:

这是一个完全的猜测,但在粗略查看数据表之后......

我认为您混淆了TRIS 端口的值。 second set_tris_b 调用应该有 0b00000000 来设置输出的所有位(并且 0b11111111 因为你有设置输入的所有位)。 p>

我不确定您是否可以使用 单个 8 位端口来做到这一点。输入值需要四位。但是,您需要 7 位输出到 7 段显示器。

这加起来超过 8 位。所以,我认为你需要两个端口。由于您使用的是端口“b”,我假设有一个端口“a”。

也许可以像您所做的那样对输入和输出的给定位进行时分复用,但我认为这很冒险,而且我对 18F 端口的细节了解不够可以肯定地说。

这里的重构代码假定一个单独的端口“a”:

void
main()
{

    while (true) {
        // set port B lower four bits for input
        SET_TRIS_B(0b00001111);

        // get input and mask off don't care bits
        DSPIN = input_b();
        DSPIN &= 0b00001111;

        if ((DSPIN >= 0b00000000) && (DSPIN <= 0b00001111))
            DSPOUT = DSPIN;
        else
            DSPOUT = 0;

        delay_ms(1000);

        // set port A pins for output
        SET_TRIS_A(0b00000000);

        if ((DSPOUT >= 0) && (DSPOUT <= 15))
            output_a(DSPVALOR[DSPOUT]);
        else
            output_a(DSPVALOR[0]);

        delay_ms(1000);
    }
}

但是,如果 18F 可以让您动态更改三态位,并且您可以连接两者输入位开关打开位 0-3 和 0-6 位上的 7 段输出位,您可以简单地将所有 *_a 调用更改为 *_b 调用。


更新 #2:

经过进一步的思考[再次,这是推测],如果 18F允许一个端口在输入和输出之间反复来回切换,“上述代码中的“占空比”[可能]不正确。

两个延迟均为 1000 毫秒,输出的占空比 [仅] 50%,因此 7 段显示器可能会严重闪烁。

这是因为,当处于三态/输入模式时,7 段显示器没有被正确的段掩码/输出值驱动

解决方案是将占空比增加到(例如)99.44% [象牙皂的纯度 :-)]。因此,大多数时间,端口处于输出模式。我们只简单地进入三态/输入模式来采样[DIP switch]输入引脚。

这是一个重构版本,它使端口大部分时间保持在输出模式:

// NOTE: these may be need to be adjusted
enum {
    INPUT_STABILIZE_DELAY =     1,      // as short as possible
    OUTPUT_STABILIZE_DELAY =    1,      // as short as possible
    OUTPUT_HOLD_DELAY =         100,    // as long as possible
};

void
main()
{

    while (true) {
        // set port B lower four bits for input
        SET_TRIS_B(0b00001111);

        // allow port to stabilize
        delay_ms(INPUT_STABILIZE_DELAY);

        // get input and mask off don't care bits
        DSPIN = input_b();
        DSPIN &= 0b00001111;

        // set output mode based on input
        if ((DSPIN >= 0b00000000) && (DSPIN <= 0b00001111))
            DSPOUT = DSPIN;
        else
            DSPOUT = 0;

        // set port B pins for output
        SET_TRIS_B(0b00000000);

        // allow tristate pins to stabilize
        delay_ms(OUTPUT_STABILIZE_DELAY);

        // output to 7 segment delay
        output_b(DSPVALOR[DSPOUT]);

        // ensure that port is in output mode 99.44% of the time
        delay_ms(OUTPUT_HOLD_DELAY);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-08
    • 1970-01-01
    • 1970-01-01
    • 2022-07-20
    • 1970-01-01
    • 2022-10-07
    • 2020-05-03
    • 1970-01-01
    相关资源
    最近更新 更多