自学内容网 自学内容网

使用国产仿真平台SmartEDA,进行Arduino仿真设计之简易红绿灯设计(二)

效果图
效果:

代码:

// 定义第一个数码管引脚连接到Arduino的引脚号(共阴极数码管,不包含小数点引脚)
const int segmentPins1[] = {0, 1, 2, 3, 4, 5, 6};
// 定义第一个方向的三个灯(红、绿、黄)连接到Arduino的引脚号
const int ledPins1[4][3] = {7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 ,18 };



//数码管显示数字对应的段码(共阴极),1 - d的显示编码
const unsigned char numCodes[] = {
    0b00000110,  // 1
    0b01011011,  // 2
    0b01001111,  // 3
    0b01100110,  // 4
    0b01101101,  // 5
    0b01111101,  // 6
    0b00000111,  // 7
    0b01111111,  // 8
    0b01101111,  // 9
};




unsigned char led_status = 0;             // 当前的方向状态机
unsigned char led_light_status = 2;       // 用于记录第某个方向相关的灯的状态
unsigned char led_time_all = 12;          // 用于记录第一个方向相关的灯的总时间,初始值为13,单位为秒
unsigned char led_time_s_flag = 0;        // 是否达到一秒的时间间隔的标志位
unsigned char led_time_shalf_flag = 0;    // 是否达到半秒的时间间隔标志位,初始值为0,达到时会被设置为1



ISR(TIMER0_COMPA_vect);
void LedTimeProcess(void);
void LedRefresh(void);
void TubeRefresh(void);



void displayNumber(int pins[], int number) ;

void setup() 
{
    // 初始化第一个数码管引脚为输出模式
    for (int i = 0; i < 7; i++) 
    {
        pinMode(segmentPins1[i], OUTPUT);
    }
    // 初始化第一个方向的灯引脚为输出模式
    for (int i = 0; i < 4; i++) 
    {
        for(int j = 0; j < 3; j++)
        {
            pinMode(ledPins1[i][j], OUTPUT);
        }
        
    }

    // 设置定时器0
    TCCR0A = 0;
    TCCR0B = 0;
    TCNT0 = 0;

    // 设置比较匹配值,每1毫秒触发一次中断
    OCR0A = 125;

    // 设置定时器模式为CTC(比较匹配时清零)
    TCCR0A |= (1 << WGM01);

    // 设置预分频器,这里选择64分频
    TCCR0B |= (1 << CS01) | (1 << CS00);

    // 使能定时器0中断
    TIMSK0 |= (1 << OCIE0A);
    // 开启全局中断使能,确保定时器中断能够被响应
    sei();
}

void loop() 
{
    LedTimeProcess();
    LedRefresh();
    TubeRefresh();

}


// 定时器中断服务函数,每1毫秒触发一次
ISR(TIMER0_COMPA_vect) 
{
  static unsigned int i = 0;
  if(++i >= 1000)
  {
      i = 0;
      led_time_s_flag = 1;
  }
}


void LedTimeProcess(void)
{
    if(led_time_s_flag == 1)
    {
        led_time_s_flag = 0;

        if(--led_time_all <= 0)
        {
            led_time_all = 12;
            led_light_status = 2;
            if(++led_status >= 4)
            {
                led_status = 0;
            }
        }



        switch(led_light_status)
        {
            case 0:

            break;
            case 1:

            break;
            case 2:
                if(led_time_all<=3)
                {
                    led_light_status = 1;
                }
            break;
        }

    } 


}

void LedRefresh(void)
{
    for(int i = 0; i < 4; i++)
    {
        if(i == led_status)
        {
            switch(led_light_status)
            {
                case 0:
                    digitalWrite(ledPins1[i][0], HIGH);
                    digitalWrite(ledPins1[i][1], LOW);
                    digitalWrite(ledPins1[i][2], LOW);  
                break;
                case 1:
                    digitalWrite(ledPins1[i][0], LOW);
                    digitalWrite(ledPins1[i][1], LOW);
                    digitalWrite(ledPins1[i][2], HIGH);
                break;
                case 2:
                    digitalWrite(ledPins1[i][0], LOW);
                    digitalWrite(ledPins1[i][1], HIGH);
                    digitalWrite(ledPins1[i][2], LOW);
                break;
            }
        }
        else
        {
             digitalWrite(ledPins1[i][0], HIGH);
             digitalWrite(ledPins1[i][1], LOW);
             digitalWrite(ledPins1[i][2], LOW);
        }
    }
   
}


void TubeRefresh(void)
{
  switch(led_light_status)
  {
      case 0:
      break;
      case 1:
        displayNumber(segmentPins1 , led_time_all);
      break;
      case 2:
        displayNumber(segmentPins1 , led_time_all-3);
      break;
  }
}



// 函数用于在给定的数码管上显示给定的数字
void displayNumber(int pins[], int number) 
{
    if (number >= 1 && number <= 9) 
    {
        unsigned char code = numCodes[number-1];
        for (int i = 0; i < 7; i++) 
        {
            digitalWrite(pins[i], bitRead(code, i));
        }
    }

}

代码阐述:

一、硬件连接定义

  • 定义了一个共阴极数码管连接到 Arduino 的引脚数组segmentPins1,以及一个二维数组ledPins1用于表示四个方向每组三个灯(红、绿、黄)连接到 Arduino 的引脚号。
  • 还定义了数码管显示数字(1 - 9)对应的共阴极段码数组numCodes

二、状态及时间相关变量

  • 声明了一些变量用于记录状态和时间信息,如方向状态机led_status、灯的状态led_light_status、灯的总时间led_time_all以及用于标记一秒和半秒时间间隔的标志位led_time_s_flagled_time_shalf_flag

三、函数声明

  • 声明了定时器中断服务函数ISR(TIMER0_COMPA_vect)、时间处理函数LedTimeProcess、指示灯刷新函数LedRefresh、数码管刷新函数TubeRefresh以及数码管显示数字函数displayNumber

四、初始化函数setup

  • 初始化数码管引脚和灯引脚为输出模式。
  • 设置定时器 0 的相关参数,包括清零、设置比较匹配值、选择定时器模式及预分频器,最后使能定时器 0 中断并开启全局中断使能。

五、主循环函数loop

  • 在主循环中依次调用LedTimeProcessLedRefreshTubeRefresh函数,以持续更新状态和刷新显示。

六、具体函数实现

  • ISR(TIMER0_COMPA_vect):定时器中断服务函数,每 1 毫秒触发一次,当计数达到 1000(即 1 秒)时设置led_time_s_flag为 1。
  • LedTimeProcess:根据led_time_s_flag判断是否达到一秒间隔,进行时间递减、状态切换等操作,如时间归零时重置并更新led_statusled_light_status
  • LedRefresh:根据led_statusled_light_status设置对应ledPins1引脚的输出电平,控制指示灯亮灭。
  • TubeRefresh:根据led_light_status调用displayNumber函数在数码管上显示不同数字,展示与时间相关信息。
  • displayNumber:根据传入数字从numCodes数组获取段码,设置数码管引脚电平以显示相应数字。

总体而言,代码通过定时器中断控制,实现了基于 Arduino 的数码管和多个方向指示灯的协同工作,根据时间和状态变化展示不同信息。


原文地址:https://blog.csdn.net/qq_64777806/article/details/143907725

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!