【问题标题】:atmega32 8x8 led matrix controlatmega32 8x8 LED 矩阵控制
【发布时间】:2020-09-25 04:57:53
【问题描述】:

我正在学习 avr,我有一个任务:在 led 8x8 矩阵上创建运行点。 从上到下和从下到上两种方式。 案例 0:没有 LED 工作(启动微控制器后默认) 案例一:从上到下 案例2:从下到上 从上到下:

for(int a=0;a<20;a++)
    {
        for (int i=0;i<8;i++)
        {
            PORTC = ~PORT[i];
            for (int i=0;i<8;i++)
            {
                PORTA = (1<<i);
                _delay_ms(200);
            }
            PORTC = PORT[i];

            PORTC = ~PORT[i+1];
            for (int i=7;i>=0;i--)
            {
                PORTA = (1<<i);
                _delay_ms(200);
            }
            i=i+1;
        }
    }

从下到上:

for(int a=0;a<20;a++)
    {
        for (int i=7;i>=0;i--)
        {
            PORTC = ~PORT[i];
            for (int c=7;c>=0;c--)
            {
                PORTA = (1<<c);
                _delay_ms(200);
            }
            PORTC = PORT[i];

            PORTC = ~PORT[i-1];
            for (int c=0;c<8;c++)
            {
                PORTA = (1<<c);
                _delay_ms(200);
            }
            i=i-1;
        }
    }

这部分对我来说很好用。 但我需要通过点击按钮来切换它们。 (中断方法)。如果我第一次单击按钮,模式切换到案例 1,但在第二次按下按钮后,它不再对我有用。

完整代码

#include <avr/interrupt.h>
#include <avr/io.h>
#include <util/delay.h>
#define F_CPU 16000000UL
volatile int state = 0;
volatile int status = 0;
char PORT[8] = {1,2,4,8,16,32,64,128};
int i;

ISR(INT0_vect)
{
    //_delay_ms(200);
    if(status==0)
    {
        state=1;
    }
    else if(status==1) 
    {
        state=2;
    }
    else if(status==2)
    {
        state=1;
    }
}

void init()
{
    DDRA = 0xFF; //PORTA as output
    DDRC = 0xFF; //PORTC as output
    DDRD=0;         /* PORTD as input */
    PORTD=0xFF;
     GICR |= (1<<INT0);
     MCUCR |= (1<<ISC01)|(1<<ISC00);
}

void zigzaglab()
{
    for(int a=0;a<20;a++)
    {
        for (int i=0;i<8;i++)
        {
            PORTC = ~PORT[i];
            for (int i=0;i<8;i++)
            {
                PORTA = (1<<i);
                _delay_ms(200);
            }
            PORTC = PORT[i];

            PORTC = ~PORT[i+1];
            for (int i=7;i>=0;i--)
            {
                PORTA = (1<<i);
                _delay_ms(200);
            }
            i=i+1;
        }
    }
}

void zigzagkreis()
{
    for(int a=0;a<20;a++)
    {
        for (int i=7;i>=0;i--)
        {
            PORTC = ~PORT[i];
            for (int c=7;c>=0;c--)
            {
                PORTA = (1<<c);
                _delay_ms(200);
            }
            PORTC = PORT[i];

            PORTC = ~PORT[i-1];
            for (int c=0;c<8;c++)
            {
                PORTA = (1<<c);
                _delay_ms(200);
            }
            i=i-1;
        }
    }
}

int main(void)
{
    init();
    sei();

    while(1)
    {
        switch(state){
            case 0:
                status=0;
                PORTC = 0;
                PORTA = 0;
                break;
            case 1:
                status=1;
                zigzaglab();
                break;
            case 2:
                status=1;
                zigzagkreis();
                break;
        }
    }
}

PS。我正在使用 proteus 8。 Proteus project

【问题讨论】:

  • 是否在您的系统上编写int 和原子操作?如果没有,您需要一个守卫来防止在写入statestatus 时读取。在你的主 while 循环中,case 0 应该给循环增加一些延迟。如果您连续几次遇到这种情况,请将处理器置于低功耗状态,等待中断状态。大多数这些系统的库中都有sleep(ms) 或类似的东西。
  • 我认为您在分配给statestatus 的作业中有错字。写下一张表格,说明它们的值在运行时如何变化。 --(是的,我也不认为对int 变量的赋值是原子的。)
  • @thebusybee 哪种值类型更适合使用 int?
  • 只要你不使用读-修改-写赋值,你可以试试uint8_t

标签: c++ c microcontroller avr atmega32


【解决方案1】:

试图了解您要做什么。将您的解决方案转换为:

#define F_CPU 16000000UL

#include <avr/interrupt.h>
#include <avr/io.h>
#include <util/delay.h>

volatile int status = 0;

ISR(INT0_vect)
{
    // !!!! NEVER PUT A DELAY IN AN INTERRUPT
    //_delay_ms(200);
    
    // If you are using a push-button the interrupt will be called more than one time cause of bouncing
    
    status++;
    
    if(status > 2)
        status = 0;
}

void init()
{
    DDRA = 0xFF;    //PORTA as output
    DDRC = 0xFF;    //PORTC as output
    DDRD = 0x00;    // Not necessary (all ports are setup to input on startup!)
    PORTD = 0xFF;   // Enable pullup resistors on PORTD
    
    // Enable interrupt 0
    GICR |= (1<<INT0);
    MCUCR |= (1<<ISC01)|(1<<ISC00);
    
    // Enable interrupts globally
    sei();
}

void matrix_forward()
{
    // Possible a better solution
    // 8*8 Matrix display can be ordered like a coordinate system (x/y)
    for (unsigned char i=0; i < 20; i++)
    {
        for(unsigned char x=0; x < 8; x += 2)
        {
            // Down
            PORTC = ~(1<<x);
            
            for (unsigned char y=0; y < 8; y++)
            {
                PORTA = (1<<y);
                _delay_ms(200);
            }
            
            PORTC = (1<<x);
            
            // Up
            PORTC = ~(1<<(x + 1));
            
            for (unsigned char y=0; y < 8; y++)
            {
                PORTA = (1<<y);
                _delay_ms(200);
            }
            
            PORTC = (1<<(x + 1));
        }
    }
}

void matrix_reverse()
{
    // Possible a better solution
    // 8*8 Matrix display can be ordered like a coordinate system (x/y)
    for (unsigned char i=0; i < 20; i++)
    {
        for(unsigned char x=0; x < 8; x += 2)
        {
            // Down
            PORTC = ~(1<<(7 - x));
            
            for (unsigned char y=0; y < 8; y++)
            {
                PORTA = (1<<(7 - y));
                _delay_ms(200);
            }
            
            PORTC = (1<<(7 - x));
            
            // Up
            PORTC = ~(1<<(6 - x));
            
            for (unsigned char y=0; y < 8; y++)
            {
                PORTA = (1<<(6 - y));
                _delay_ms(200);
            }
            
            PORTC = (1<<(6 - x));
        }
    }
}

int main(void)
{
    init();

    while(1)
    {
        switch(status){
            case 0:
                PORTC = 0x00;   // for PORTs, PINs, DDRs use HEX or BINARY notation
                PORTA = 0x00;   // cause of better readiness
                break;
            case 1:
                matrix_forward();
                break;
            case 2:
                matrix_reverse();
                break;
        }
    }
}

无法检查代码,但也许您可以为您的解决方案提取一些代码!

【讨论】:

  • 问题已修复,只是模拟器问题 ;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-15
  • 1970-01-01
相关资源
最近更新 更多