• arduino之16*16点阵庆祝祖国70周年


      之前电脑上存了很多自己写的关于arduino的有趣的小demo,因为重装了系统,不小心误删了所有的文件(气的半死),所以现在准备一有空就重写一下之前写过的东东,顺带再温习一次,这次总不能再删了吧,嘿嘿。

    这次主要想记录一下点阵的使用,方便以后查阅,也分享出来和伙伴们一起学习进步。这次在代码中,用的最多的就是指针的使用,就当回顾知识点了。

      用到的材料:一个16*16点阵(由4块8*8的led点阵组成的),arduino的uno。

      用到的库文件:LedControl.h ,因为点阵是使用的max7219,这个库很不错。

    先看看效果,下面是视频链接:

    arduino之庆祝祖国70周年

    下面直接上代码,有兴趣的小伙伴可以玩玩。

      1 #include <LedControl.h>
      2 const int DIN = 12;
      3 const int CLK = 10;
      4 const int CS = 11;
      5 int maxLen;//字的总个数
      6 int row;//纵向移动数组的行数
      7 int col;//横向移动数组的列数
      8 //自定义函数
      9 void showWordByArr(LedControl led, byte[][2]); //通过数组显示
     10 void showWordByPtr(LedControl led, byte(*word)[2]); //通过数组指针显示
     11 void showWords(LedControl led, byte(*words)[16][2]); //显示一组文字
     12 void showTopMoveWords(LedControl led, byte(*words)[16][2]); //向上移动显示文字
     13 void showLeftMoveWords(LedControl led, byte(*words)[16][2]); //向左移动显示文字
     14 
     15 //初始化对象,每个对象最多可以操作8个设备(超过8个设备就再创建一个对象)。
     16 LedControl led = LedControl(DIN, CLK, CS , 4);//我这里是4块8*8的led点阵,所以设备数量填4(最大为8)。
     17 byte a[][2] =  //实心五角星
     18 {
     19   0x01, 0x00, //第一,二个设备
     20   0x01, 0x00,
     21   0x03, 0x80,
     22   0x03, 0x80,
     23   0x03, 0x80,
     24   0x07, 0xC0,
     25   0xFF, 0xFE,
     26   0x7F, 0xFC,
     27   0x3F, 0xF8, //第三,四个设备
     28   0x0F, 0xE0,
     29   0x0F, 0xE0,
     30   0x1F, 0xF0,
     31   0x1E, 0xF0,
     32   0x18, 0x30,
     33   0x20, 0x08,
     34   0x00, 0x00
     35 };
     36 byte b[][2] =  //空心五角星
     37 {
     38   0x01, 0x00, 0x01, 0x00, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x04, 0x40, 0xFC, 0x7E, 0x40, 0x04,
     39   0x30, 0x18, 0x08, 0x20, 0x08, 0x20, 0x11, 0x90, 0x16, 0x50, 0x18, 0x30, 0x20, 0x08, 0x00, 0x00
     40 };
     41 byte c[][2] =  //空心取反
     42 {
     43   0xFE, 0xFF, 0xFE, 0xFF, 0xFC, 0x7F, 0xFC, 0x7F, 0xFC, 0x7F, 0xF8, 0x3F, 0x00, 0x01, 0x80, 0x03,
     44   0xC0, 0x07, 0xF0, 0x1F, 0xF0, 0x1F, 0xE0, 0x0F, 0xE1, 0x0F, 0xE7, 0xCF, 0xDF, 0xF7, 0xFF, 0xFF
     45 };
     46 
     47 byte topWords[][16][2] = //庆祝祖国70周年
     48 {
     49   {0x00},
     50   { 
     51       0x01, 0x00, 0x00, 0x80, 0x3F, 0xFE, 0x20, 0x00, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x2F, 0xFC,
     52       0x20, 0x80, 0x21, 0x40, 0x21, 0x40, 0x22, 0x20, 0x42, 0x20, 0x44, 0x10, 0x88, 0x08, 0x10, 0x06
     53   },
     54   {
     55       0x20, 0x00, 0x13, 0xFC, 0x12, 0x04, 0xFA, 0x04, 0x0A, 0x04, 0x12, 0x04, 0x13, 0xFC, 0x38, 0x90,
     56       0x54, 0x90, 0x94, 0x90, 0x10, 0x90, 0x11, 0x12, 0x11, 0x12, 0x12, 0x12, 0x14, 0x0E, 0x18, 0x00
     57   },
     58   { 
     59       0x20, 0x00, 0x11, 0xF8, 0x11, 0x08, 0xF9, 0x08, 0x09, 0x08, 0x11, 0xF8, 0x11, 0x08, 0x39, 0x08,
     60       0x55, 0x08, 0x95, 0xF8, 0x11, 0x08, 0x11, 0x08, 0x11, 0x08, 0x11, 0x08, 0x17, 0xFE, 0x10, 0x00
     61   },
     62   { 
     63       0x00, 0x00, 0x7F, 0xFC, 0x40, 0x04, 0x40, 0x04, 0x5F, 0xF4, 0x41, 0x04, 0x41, 0x04, 0x4F, 0xE4,
     64       0x41, 0x04, 0x41, 0x44, 0x41, 0x24, 0x5F, 0xF4, 0x40, 0x04, 0x40, 0x04, 0x7F, 0xFC, 0x40, 0x04
     65   },
     66   { 
     67       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x18, 0x44, 0x24, 0x44, 0x42, 0x08, 0x42, 0x08, 0x42,
     68       0x10, 0x42, 0x10, 0x42, 0x10, 0x42, 0x10, 0x24, 0x10, 0x18, 0x00, 0x00, 0x00, 0x00
     69   },
     70   { 
     71       0x00, 0x00, 0x3F, 0xF8, 0x21, 0x08, 0x21, 0x08, 0x2F, 0xE8, 0x21, 0x08, 0x21, 0x08, 0x3F, 0xF8,
     72       0x20, 0x08, 0x27, 0xC8, 0x24, 0x48, 0x24, 0x48, 0x27, 0xC8, 0x40, 0x08, 0x40, 0x28, 0x80, 0x10
     73   },
     74   { 
     75       0x10, 0x00, 0x10, 0x00, 0x1F, 0xFC, 0x20, 0x80, 0x20, 0x80, 0x40, 0x80, 0x1F, 0xF8, 0x10, 0x80,
     76       0x10, 0x80, 0x10, 0x80, 0xFF, 0xFE, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80
     77   },
     78   {
     79       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
     80       0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x30,0x00,0x10,0x00,0x20,0x00,0x00,0x00
     81   }
     82  
     83 };
     84 byte words[][16][2]= //愿祖国繁荣昌盛,越来越好,
     85 {
     86     {
     87         0x00,0x00,0x3F,0xFE,0x20,0x80,0x27,0xF8,0x24,0x08,0x27,0xF8,0x24,0x08,0x27,0xF8,
     88         0x22,0x50,0x24,0x48,0x29,0x44,0x20,0x80,0x20,0x44,0x4A,0x42,0x4A,0x12,0x91,0xF0
     89     },
     90     { 
     91         0x20,0x00,0x11,0xF8,0x11,0x08,0xF9,0x08,0x09,0x08,0x11,0xF8,0x11,0x08,0x39,0x08,
     92         0x55,0x08,0x95,0xF8,0x11,0x08,0x11,0x08,0x11,0x08,0x11,0x08,0x17,0xFE,0x10,0x00
     93     },
     94     { 
     95         0x00,0x00,0x7F,0xFC,0x40,0x04,0x40,0x04,0x5F,0xF4,0x41,0x04,0x41,0x04,0x4F,0xE4,
     96         0x41,0x04,0x41,0x44,0x41,0x24,0x5F,0xF4,0x40,0x04,0x40,0x04,0x7F,0xFC,0x40,0x04
     97     },
     98     {
     99         0x20,0x20,0x3F,0x20,0x40,0x3E,0xBE,0x48,0x2A,0xA8,0xFF,0x28,0x4A,0x10,0x7F,0x28,
    100         0x04,0x46,0x08,0x80,0x1F,0x00,0x02,0x10,0x3F,0xF8,0x01,0x08,0x15,0x20,0x22,0x10
    101     },
    102     {
    103         0x08,0x20,0x08,0x20,0xFF,0xFE,0x08,0x20,0x00,0x00,0x7F,0xFE,0x40,0x02,0x81,0x04,
    104         0x01,0x00,0x7F,0xFC,0x03,0x80,0x05,0x40,0x09,0x20,0x31,0x18,0xC1,0x06,0x01,0x00
    105     },
    106     {
    107         0x1F,0xF0,0x10,0x10,0x10,0x10,0x1F,0xF0,0x10,0x10,0x10,0x10,0x1F,0xF0,0x00,0x00,
    108         0x3F,0xF8,0x20,0x08,0x20,0x08,0x3F,0xF8,0x20,0x08,0x20,0x08,0x3F,0xF8,0x20,0x08
    109     },
    110     {
    111         0x00,0x90,0x00,0x88,0x3F,0xFC,0x20,0x80,0x20,0x88,0x3E,0x48,0x22,0x50,0x22,0x24,
    112         0x4A,0x54,0x44,0x8C,0x81,0x04,0x3F,0xF8,0x24,0x48,0x24,0x48,0xFF,0xFE,0x00,0x00
    113     },
    114     {
    115         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    116         0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x30,0x00,0x10,0x00,0x20,0x00,0x00,0x00
    117     },
    118     {
    119         0x10,0x28,0x10,0x24,0x10,0x20,0x7D,0xFC,0x11,0x20,0x11,0x24,0xFD,0x24,0x11,0x28,
    120         0x11,0x28,0x51,0x10,0x5D,0x94,0x51,0x2C,0x70,0x44,0x50,0x00,0x4F,0xFE,0x80,0x00
    121     },
    122     {
    123         0x01,0x00,0x01,0x00,0x01,0x00,0x7F,0xFC,0x01,0x00,0x11,0x10,0x09,0x10,0x09,0x20,
    124         0xFF,0xFE,0x03,0x80,0x05,0x40,0x09,0x20,0x31,0x18,0xC1,0x06,0x01,0x00,0x01,0x00
    125     },
    126     {
    127         0x10,0x28,0x10,0x24,0x10,0x20,0x7D,0xFC,0x11,0x20,0x11,0x24,0xFD,0x24,0x11,0x28,
    128         0x11,0x28,0x51,0x10,0x5D,0x94,0x51,0x2C,0x70,0x44,0x50,0x00,0x4F,0xFE,0x80,0x00
    129     },
    130     {
    131         0x10,0x00,0x10,0xFC,0x10,0x04,0x10,0x08,0xFC,0x10,0x24,0x20,0x24,0x20,0x25,0xFE,
    132         0x24,0x20,0x48,0x20,0x28,0x20,0x10,0x20,0x28,0x20,0x44,0x20,0x84,0xA0,0x00,0x40
    133     },
    134     {
    135         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    136         0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x30,0x00,0x10,0x00,0x20,0x00,0x00,0x00
    137     }
    138 };
    139 byte leftWords[][16][2]=  //我爱你中国!
    140 {
    141     {
    142         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    143         0x00,0x00,0x1A,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
    144     },
    145     {
    146         0x04,0x24,0x24,0x24,0x7F,0xC4,0x44,0x04,0x04,0xFF,0x04,0x44,0x34,0x05,0x04,0x00,
    147         0x00,0x10,0x12,0x21,0xFE,0x40,0x82,0x02,0x04,0xC8,0x30,0x28,0x44,0x82,0x1F,0x00
    148     },
    149     {
    150         0x01,0x26,0x34,0x2C,0x24,0x24,0x37,0x4C,0x44,0x44,0x4C,0x74,0xC4,0x45,0x06,0x00,
    151         0x00,0x82,0x84,0x89,0x91,0xE1,0xB2,0xAA,0xA4,0xA4,0xAA,0xB2,0x81,0x01,0x01,0x00
    152     },
    153     {
    154         0x00,0x01,0x06,0x1F,0xE0,0x02,0x04,0x18,0xF0,0x10,0x13,0x10,0x10,0x14,0x18,0x00,
    155         0x80,0x00,0x00,0xFF,0x00,0x08,0x30,0xC0,0x02,0x01,0xFE,0x00,0x80,0x60,0x18,0x00
    156     },
    157     {
    158         0x00,0x00,0x0F,0x08,0x08,0x08,0x08,0xFF,0x08,0x08,0x08,0x08,0x0F,0x00,0x00,0x00,
    159         0x00,0x00,0xF0,0x20,0x20,0x20,0x20,0xFF,0x20,0x20,0x20,0x20,0xF0,0x00,0x00,0x00
    160     },
    161     {
    162         0x00,0x7F,0x40,0x48,0x49,0x49,0x49,0x4F,0x49,0x49,0x49,0x48,0x40,0x7F,0x00,0x00,
    163         0x00,0xFF,0x02,0x12,0x12,0x12,0x12,0xF2,0x12,0x52,0x32,0x12,0x02,0xFF,0x00,0x00
    164     },
    165     {
    166         0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    167         0x00,0x00,0x00,0xCC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
    168     }
    169 };
    170 
    171 
    172 void setup() {
    173   for (int i = 0; i < 4; ++i)
    174   {
    175     led.shutdown(i, false);//关闭省电模式,这一步必须做,否则显示不出来(因为在构造函数中,默认开启了省电模式,所以,我们要关闭该模式)。
    176     led.clearDisplay(i);//清空数据
    177   }
    178   maxLen = sizeof(words)/sizeof(*words);//计算总的字数
    179   row = 16 * (sizeof(topWords) / sizeof(*topWords));//计算向上移动的字的总行数
    180   col = 16 * (sizeof(leftWords) / sizeof(*leftWords));//计算向左移动的字的总列数
    181 }
    182 
    183 void loop() {
    184   // put your main code here, to run repeatedly:
    185   showWordByPtr(led, b); //显示空心五角星
    186   delay(500);
    187   for(int i =0;i<5;++i)
    188   {
    189     showWordByArr(led, a); //实心五角星
    190     delay(200);
    191     showWordByArr(led, c); //空心取反
    192     delay(200);
    193   }
    194   showWordByArr(led, a); //实心五角星
    195   delay(800);
    196   showTopMoveWords(led, topWords); //字向左滚动
    197   delay(500);
    198   showWords(led, words); //字原地变换
    199   delay(100);
    200   showLeftMoveWords(led, leftWords); //字向右滚动
    201   delay(1000);
    202 }
    203 
    204 void showWordByArr(LedControl led, byte word[][2]) 
    205 {
    206   for (int i = 0; i < 4; ++i)
    207   {
    208     if (i < 2)
    209     {
    210       for (int j = 0; j < 8; ++j)
    211       {
    212         led.setRow(i, j, word[j][i]);
    213       }
    214     }
    215     else
    216     {
    217       for (int j = 0; j < 8; ++j)
    218       {
    219         led.setRow(i, j, word[j + 8][i - 2]);
    220       }
    221     }
    222   }
    223 }
    224 
    225 void showWordByPtr(LedControl led, byte (*word)[2])
    226 {
    227   for (int i = 0; i < 4; ++i)
    228   {
    229     if (i < 2)
    230     {
    231       for (int j = 0; j < 8; ++j)
    232       {
    233         led.setRow(i, j, *(*(word + j) + i));
    234       }
    235     }
    236     else
    237     {
    238       for (int j = 0; j < 8; ++j)
    239       {
    240         led.setRow(i, j, *(*(word + j + 8) + i - 2));
    241       }
    242     }
    243   }
    244 }
    245 
    246 void showWords(LedControl led, byte (*words)[16][2])
    247 {
    248   for (int i = 0; i < maxLen; ++i)
    249   {
    250     showWordByPtr(led, *(words + i));
    251     delay(800);
    252   }
    253 }
    254 
    255 void showTopMoveWords(LedControl led, byte(*words)[16][2])
    256 {
    257   byte *temp = *(*words); //获取第一个二维数组的第一行的(第一个元素)的指针
    258   byte* dump = temp;
    259   for(int n =0;n<=row-16;++n)
    260   {
    261     dump = temp;
    262     for (int i = 0; i < 4; ++i)//共4块8*8led点阵,每块显示完再到下一块
    263     {
    264       dump = temp;
    265       if (i < 2)  //第一、二块的点阵
    266       {
    267         for (int j = 0; j < 8; ++j)  //每块点阵共8行,所以循环8次
    268         {
    269           led.setRow(i, j, *(dump + i));
    270           dump+=2;  //指向下一行的第一个位置
    271         }
    272       }
    273       else  //第三、四块点阵显示
    274       {
    275         dump+=16;  //因为是显示二维数组的后半部分,这里要加一下。
    276         for (int j = 0; j < 8; ++j)
    277         {
    278           led.setRow(i, j, *(dump+i-2));
    279           dump+=2;
    280         }
    281       }
    282     }
    283     temp += 2;//每次循环完,指向下一行。
    284     delay(35); //每次显示之间间隔35ms,这是我自己测试的,如果想要更快或更慢可以相应调整这个参数。
    285   }
    286 }
    287 
    288 void showLeftMoveWords(LedControl led, byte(*words)[16][2])
    289 {
    290     byte* first = *(*words);
    291     byte* firstChangeFlag = first + 15;//开始遍历的指针需要变换的标志(也就是当first和firstChangeFlag相等时,说明first需要再偏移17).
    292     byte* temp = first; //负责显示第一、二个led点阵的指针
    293     byte* temp1 = first + 16; //负责显示第三、四个点阵的指针
    294     for (int n = 0; n < col - 16; ++n)
    295     {
    296         temp = first;
    297         temp1 = first + 16;
    298         for (int i=0;i<4;++i)
    299         {
    300             if (i < 2) //第一、二个点阵
    301             {
    302                 for (int j = 0; j < 8; ++j)
    303                 {
    304                     led.setColumn(i, j, *temp);
    305                     if (temp == firstChangeFlag)
    306                     {
    307                         temp += 17;
    308                     }
    309                     else
    310                     {
    311                         temp++;
    312                     }
    313                 }
    314             }
    315             else  //第三、四个点阵
    316             {
    317                 for (int k=0; k<8; ++k)
    318                 {
    319                     led.setColumn(i, k, *temp1);
    320                     if (temp1 == firstChangeFlag+16)
    321                     {
    322                         temp1 += 17;
    323                     }
    324                     else
    325                     {
    326                         temp1++;
    327                     }
    328                 }
    329             }
    330         }
    331         if (first == firstChangeFlag)
    332         {
    333             first += 17;
    334             firstChangeFlag = first + 15;
    335         }
    336         else
    337         {
    338             first++;
    339         }
    340         //delay(1000);
    341     }
    342 }

    最后总结一下:

      1. 汉字的点阵数组是使用16*16字模软件提取出来的,我用的是字模提取 v2.2版本,网上搜一下就有。

      2. 原来写过的,只是单纯的显示汉字,这次把文字移动显示加上去了。

      3. 向左移动文字的那个函数想了好久才写出来的,主要是太浮躁了,后来静下心来仔细推敲,是发现指针遍历数组的顺序有问题,这才解决了。

      4. 通过视频可以看到,向左移动显示的效果还是有点问题的,上面一半的显示和下面一半的显示有一点不同步,难道是处理器跟不上?(自我安慰)。希望有路过大神指点一下。

      5. 最后要感谢下面的文章,是当初玩点阵入门的时候的参考资料。

    LedControl库的使用

    Arduino Uno 使用MAX7219驱动单个8*8点阵LED模块 - 凌顺实验室

    2019-10-15更新:

      今天上班钻孔的时候(我是做模具的),突然来了灵感,想到了解决横向滚动,上下屏不同步的解决办法。

    回来一试,效果很好(几乎看不出来,不同步了)。原来我是按照先显示第1和第2块led点阵,再显示第3块和第4块点阵的方式的(这是向上滚动字幕的显示方式),

    既然向左滚动,那应该是先显示最左边的点阵,即先显示第1和第3块点阵,再显示右边的第2和第4块led点阵,这样就解决了,代码稍加改动如下:

     1 void showLeftMoveWords(LedControl led, byte(*words)[16][2])
     2 {
     3     byte* first = *(*words);
     4     byte* firstChangeFlag = first + 15;//开始遍历的指针需要变换的标志(也就是当first和firstChangeFlag相等时,说明first需要再偏移17).
     5     byte* temp = first; //负责显示第一、二个led点阵的指针
     6     byte* temp1 = first + 16; //负责显示第三、四个点阵的指针
     7     for (int n = 0; n < col - 16; ++n)
     8     {
     9         temp = first;
    10         temp1 = first + 16;
    11         //原来是先显示第1块和第2块,再显示第3,4块的,所以导致上下屏不同步。
    12         for (int i = 0; i < 2; ++i)  //这里循环2次,分2次显示,先显示第1块和第3块led,再显示第2块和第4块led。
    13         {
    14             for (int j = 0; j < 8; ++j) 
    15             {
    16                 led.setColumn(i, j, *temp);
    17                 if (temp == firstChangeFlag)
    18                 {
    19                     temp += 17;
    20                 }
    21                 else
    22                 {
    23                     temp++;
    24                 }
    25             }
    26             for (int k = 0; k < 8; ++k)
    27             {
    28                 led.setColumn(i+2, k, *temp1);
    29                 if (temp1 == firstChangeFlag + 16)
    30                 {
    31                     temp1 += 17;
    32                 }
    33                 else
    34                 {
    35                     temp1++;
    36                 }
    37             }
    38         }
    39         if (first == firstChangeFlag)
    40         {
    41             first += 17;
    42             firstChangeFlag = first + 15;
    43         }
    44         else
    45         {
    46             first++;
    47         }
    48     }
    49 }

    再次总结:

      1. 这个点阵模块在某宝上花了三十几块大洋买的,玩到这样也算对的起我的大洋了。。。

      2. 突然发现,点阵可以拿来玩一些数据结构的演练,有空得好好试下玩玩(比如,拿这点阵玩贪吃蛇。。。)。

      3. 遇到问题,一定要冷静思考,切勿焦躁,烦躁是大忌,这也是成为一名职业程序员的基本修养(虽然,目前还不是)。

  • 相关阅读:
    Django基础
    DRF初始化/DRF认证、权限、限流、分页、过滤、序列化
    Pyinstaller安装和使用
    爬虫概述
    django在test.py测试文件中的配置
    django ORM 多对多关系
    django中的分页
    vue安装及新建项目
    app应用路由设置
    Django之Session与Cookie原理及区别
  • 原文地址:https://www.cnblogs.com/dz-study/p/11627740.html
Copyright © 2020-2023  润新知