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

效果图
效果:

代码:

cpp 复制代码
// 定义第一个数码管引脚连接到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 的数码管和多个方向指示灯的协同工作,根据时间和状态变化展示不同信息。

相关推荐
Wallace Zhang36 分钟前
STM32F103_Bootloader程序开发11 - 实现 App 安全跳转至 Bootloader
stm32·嵌入式硬件·安全
GodKK老神灭40 分钟前
STM32 CCR寄存器
stm32·单片机·嵌入式硬件
杰克逊的日记9 天前
MCU编程
单片机·嵌入式硬件
Python小老六9 天前
单片机测ntc热敏电阻的几种方法(软件)
数据库·单片机·嵌入式硬件
懒惰的bit9 天前
STM32F103C8T6 学习笔记摘要(四)
笔记·stm32·学习
HX科技9 天前
STM32给FPGA的外挂FLASH进行升级
stm32·嵌入式硬件·fpga开发·flash·fpga升级
Suagrhaha10 天前
驱动入门的进一步深入
linux·嵌入式硬件·驱动
国科安芯10 天前
基于ASP4644多通道降压技术在电力监测系统中集成应用与发展前景
嵌入式硬件·硬件架构·硬件工程
Li Zi10 天前
STM32 ADC(DMA)双缓冲采集+串口USART(DMA)直接传输12位原始数据到上位机显示并保存WAV格式音频文件 收藏住绝对实用!!!
经验分享·stm32·单片机·嵌入式硬件
进击的程序汪10 天前
触摸屏(典型 I2C + Input 子系统设备)从设备树解析到触摸事件上报
linux·网络·嵌入式硬件