亚洲春色中文字幕久久久-三上亚,一吻二脱三床四吻胸,国产真实伦对白视频全集,在线毛片观看,精品成品入口黄网,国产毛aⅴ片久久久,亚洲AV色香蕉一区二区三区老师,萧皇后A级艳片,色情日本视频更新,99久久亚洲精品日本无码

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 643|回復: 6
打印 上一主題 下一主題
收起左側

一個STC單片機驅動MAX7219的音樂節拍器程序

[復制鏈接]
跳轉到指定樓層
樓主
ID:39720 發表于 2026-5-3 08:10 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
main.c
  1. #include <reg52.h>
  2. #include <intrins.h>
  3. #include "keyscan.h"

  4. // 定時器0初始化
  5. void Timer0_Init()
  6. {
  7.     TMOD |= 0x01;      // 定時器0,工作模式1
  8.     TH0 = 0xFC;        // 1ms定時
  9.     TL0 = 0x18;
  10.     ET0 = 1;           // 允許定時器0中斷
  11.     TR0 = 1;           // 啟動定時器0
  12.     EA = 1;            // 開啟總中斷
  13. }

  14. // 主函數
  15. void main()
  16. {
  17.     // 初始化
  18.     P0 = 0xFF;
  19.     P1 = 0xFF;
  20.     P2 = 0x00;  // LED初始全滅
  21.     P3 = 0xFF;

  22.     MAX7219_Init();
  23.     Clear_Display();
  24.     Display_Speed();
  25.     Display_BeatType();

  26.     Timer0_Init();

  27.     while(1)
  28.     {
  29.         Key_Scan();
  30.     }
  31. }

  32. // 定時器0中斷服務程序
  33. void Timer0_ISR() interrupt 1
  34. {
  35.     TH0 = 0xFC;        // 重新裝載初值
  36.     TL0 = 0x18;

  37.     timer_count++;

  38.     if(is_playing)
  39.     {
  40.         if(timer_count >= interval)
  41.         {
  42.             timer_count = 0;

  43.             // 產生節拍
  44.             Update_LEDs();
  45.             Output_Sound();

  46.             // 更新拍數
  47.             beat_count++;
  48.             if(beat_count >= beats_per_bar[beat_type])
  49.             {
  50.                 beat_count = 0;
  51.             }
  52.         }
  53.     }
  54. }



  55. keyscan.c
  56. #include "keyscan.h"
  57. unsigned int interval = 0;
  58. unsigned char is_playing = 0;
  59. unsigned char beat_count = 0;
  60. unsigned int timer_count = 0;
  61. // 按鍵掃描
  62. void Key_Scan()
  63. {
  64.     static unsigned char key_up_flag = 1;
  65.     static unsigned char key_down_flag = 1;
  66.     static unsigned char key_type_flag = 1;
  67.     static unsigned char key_start_flag = 1;

  68.     // 速度+按鍵
  69.     if(KEY_UP == 0)
  70.     {
  71.         if(key_up_flag)
  72.         {
  73.             key_up_flag = 0;
  74.             if(beat_speed < 240)
  75.             {
  76.                 beat_speed += 1;
  77.                 Display_Speed();
  78.                 if(is_playing)
  79.                 {
  80.                     // 重新計算間隔
  81.                     interval = 60000 / beat_speed;  // ms
  82.                 }
  83.             }
  84.         }
  85.     }
  86.     else
  87.     {
  88.         key_up_flag = 1;
  89.     }

  90.     // 速度-按鍵
  91.     if(KEY_DOWN == 0)
  92.     {
  93.         if(key_down_flag)
  94.         {
  95.             key_down_flag = 0;
  96.             if(beat_speed > 40)
  97.             {
  98.                 beat_speed -= 1;
  99.                 Display_Speed();
  100.                 if(is_playing)
  101.                 {
  102.                     interval = 60000 / beat_speed;  // ms
  103.                 }
  104.             }
  105.         }
  106.     }
  107.     else
  108.     {
  109.         key_down_flag = 1;
  110.     }

  111.     // 拍型選擇按鍵
  112.     if(KEY_TYPE == 0)
  113.     {
  114.         if(key_type_flag)
  115.         {
  116.             key_type_flag = 0;
  117.             beat_type = (beat_type + 1) % 4;
  118.             beat_count = 0;
  119.             Display_BeatType();
  120.             Update_LEDs();
  121.         }
  122.     }
  123.     else
  124.     {
  125.         key_type_flag = 1;
  126.     }

  127.     // 開始/停止按鍵
  128.     if(KEY_START == 0)
  129.     {
  130.         if(key_start_flag)
  131.         {
  132.             key_start_flag = 0;
  133.             is_playing = !is_playing;
  134.             if(is_playing)
  135.             {
  136.                 beat_count = 0;
  137.                 interval = 60000 / beat_speed;  // 計算每個節拍的時間間隔(ms)
  138.                 timer_count = 0;
  139.                 // 顯示運行狀態
  140.                 MAX7219_WriteCmd(5, 0x80);  // 在第五位顯示點
  141.             }
  142.             else
  143.             {               
  144.                 MAX7219_WriteCmd(5, 0x00);      // 顯示停止狀態               
  145.                 LED1 = LED2 = LED3 = LED4 = LED5 = LED6 = 0;  // 關閉所有LED
  146.             }
  147.         }
  148.     }
  149.     else
  150.     {
  151.         key_start_flag = 1;
  152.     }
  153. }

  154. void delay_ms(unsigned int ms)
  155. {
  156.     unsigned int i, j;
  157.     for(i = 0; i < ms; i++)
  158.         for(j = 0; j < 114; j++);
  159. }
  160. // 更新指示燈
  161. void Update_LEDs()
  162. {
  163.     LED1 = LED2 = LED3 = LED4 = LED5 = LED6 = 0;  // 先關閉所有LED

  164.     switch(beat_type)
  165.     {
  166.         case 0:  // 2/4拍
  167.             if(beat_count == 0) LED1 = 1;  // 強拍
  168.             if(beat_count == 1) LED2 = 1;  // 弱拍
  169.             break;

  170.         case 1:  // 3/4拍
  171.             if(beat_count == 0) LED1 = 1;  // 強拍
  172.             if(beat_count == 1) LED2 = 1;  // 弱拍
  173.             if(beat_count == 2) LED3 = 1;  // 弱拍
  174.             break;

  175.         case 2:  // 4/4拍
  176.             if(beat_count == 0) LED1 = 1;  // 強拍
  177.             if(beat_count == 1) LED2 = 1;  // 弱拍
  178.             if(beat_count == 2) LED3 = 1;  // 次強拍
  179.             if(beat_count == 3) LED4 = 1;  // 弱拍
  180.             break;

  181.         case 3:  // 6/8拍
  182.             if(beat_count == 0) LED1 = 1;  // 強拍
  183.             if(beat_count == 1) LED2 = 1;  // 弱拍
  184.             if(beat_count == 2) LED3 = 1;  // 弱拍
  185.             if(beat_count == 3) LED4 = 1;  // 次強拍
  186.             if(beat_count == 4) LED5 = 1;  // 弱拍
  187.             if(beat_count == 5) LED6 = 1;  // 弱拍
  188.             break;
  189.     }
  190. }

  191. // 輸出音源信號
  192. void Output_Sound()
  193. {
  194.     // 根據拍型輸出不同的音源
  195.     switch(beat_type)
  196.     {
  197.         case 0:  // 2/4拍
  198.             if(beat_count == 0)
  199.             {
  200.                 SOUND1 = 1;  // 強拍
  201.                 delay_ms(20);
  202.                 SOUND1 = 0;
  203.             }
  204.             else
  205.             {
  206.                 SOUND2 = 1;  // 弱拍
  207.                 delay_ms(10);
  208.                 SOUND2 = 0;
  209.             }
  210.             break;

  211.         case 1:  // 3/4拍
  212.             if(beat_count == 0)
  213.             {
  214.                 SOUND1 = 1;  // 強拍
  215.                 delay_ms(20);
  216.                 SOUND1 = 0;
  217.             }
  218.             else
  219.             {
  220.                 SOUND3 = 1;  // 弱拍
  221.                 delay_ms(10);
  222.                 SOUND3 = 0;
  223.             }
  224.             break;

  225.         case 2:  // 4/4拍
  226.             if(beat_count == 0)
  227.             {
  228.                 SOUND1 = 1;  // 強拍
  229.                 delay_ms(20);
  230.                 SOUND1 = 0;
  231.             } else if(beat_count == 2)
  232.             {
  233.                 SOUND2 = 1;  // 次強拍
  234.                 delay_ms(15);
  235.                 SOUND2 = 0;
  236.             }
  237.             else
  238.             {
  239.                 SOUND3 = 1;  // 弱拍
  240.                 delay_ms(10);
  241.                 SOUND3 = 0;
  242.             }
  243.             break;

  244.         case 3:  // 6/8拍
  245.             if(beat_count == 0)
  246.             {
  247.                 SOUND1 = 1;  // 強拍
  248.                 delay_ms(20);
  249.                 SOUND1 = 0;
  250.             }
  251.             else if(beat_count == 3)
  252.             {
  253.                 SOUND2 = 1;  // 次強拍
  254.                 delay_ms(15);
  255.                 SOUND2 = 0;
  256.             }
  257.             else
  258.             {
  259.                 SOUND4 = 1;  // 弱拍
  260.                 delay_ms(10);
  261.                 SOUND4 = 0;
  262.             }
  263.             break;
  264.     }
  265. }


  266. diplay.c
  267. #include "display.h"

  268. unsigned int beat_speed = 120;      // 節拍速度(BPM),默認120
  269. unsigned char beat_type = 0;        // 拍型索引 0:2/4, 1:3/4, 2:4/4, 3:6/8
  270. // 數字字體(0-9)

  271. unsigned char code font_table[] =
  272. {
  273.     0x7E, 0x30, 0x6D, 0x79, 0x33,
  274.     0x5B, 0x5F, 0x70, 0x7F, 0x7B
  275. };

  276. // 拍型對應的每小節拍數
  277. unsigned char code beats_per_bar[] = {2, 3, 4, 6};

  278. // MAX7219初始化命令
  279. unsigned char code init_cmds[][2] =
  280. {
  281.     {0x0C, 0x01},  // 關閉關機模式
  282.     {0x0B, 0x07},  // 掃描所有8位
  283.     {0x0A, 0x08},  // 亮度
  284.     {0x09, 0x00},  // 解碼模式:無
  285.     {0x0F, 0x00}   // 顯示測試:關閉
  286. };



  287. // MAX7219寫一個字節
  288. void MAX7219_WriteByte(unsigned char data_byte)
  289. {
  290.     unsigned char i;
  291.     for(i = 0; i < 8; i++)
  292.     {
  293.         MAX7219_CLK = 0;
  294.         MAX7219_DIN = (data_byte & 0x80) ? 1 : 0;
  295.         data_byte <<= 1;
  296.         MAX7219_CLK = 1;
  297.     }
  298. }

  299. // MAX7219寫命令
  300. void MAX7219_WriteCmd(unsigned char address, unsigned char data_byte)
  301. {
  302.     MAX7219_CS = 0;
  303.     MAX7219_WriteByte(address);
  304.     MAX7219_WriteByte(data_byte);
  305.     MAX7219_CS = 1;
  306. }

  307. // MAX7219初始化
  308. void MAX7219_Init()
  309. {
  310.     unsigned char i;
  311.     for(i = 0; i < 5; i++)
  312.     {
  313.         MAX7219_WriteCmd(init_cmds[i][0], init_cmds[i][1]);
  314.     }
  315. }

  316. // 在數碼管上顯示數字
  317. void Display_Number(unsigned char digit, unsigned char number)
  318. {
  319.     if(digit >= 1 && digit <= 8)
  320.     {
  321.         MAX7219_WriteCmd(digit, number);
  322.     }
  323. }

  324. // 顯示當前速度
  325. void Display_Speed()
  326. {
  327.     unsigned char bai, shi, ge;

  328.     bai = beat_speed / 100;
  329.     shi = (beat_speed % 100) / 10;
  330.     ge = beat_speed % 10;

  331.     // 顯示在4-6位數碼管上
  332.     Display_Number(3, font_table[bai]);
  333.     Display_Number(2, font_table[shi]);
  334.     Display_Number(1, font_table[ge]);
  335. }

  336. // 顯示拍型
  337. void Display_BeatType()
  338. {
  339.     switch(beat_type)
  340.     {
  341.         case 0: Display_Number(8, 0x6D);         //2
  342.                 Display_Number(7, 0x01);
  343.                 Display_Number(6, 0x33); break;  // 4
  344.         case 1: Display_Number(8, 0x79);         // 3
  345.                 Display_Number(7, 0x01);
  346.                 Display_Number(6, 0x33); break;  // 4
  347.         case 2: Display_Number(8, 0x33);         // 4
  348.                 Display_Number(7, 0x01);
  349.                 Display_Number(6, 0x33); break;  // 4
  350.         case 3: Display_Number(8, 0x5F);         // 6
  351.                 Display_Number(7, 0x01);
  352.                 Display_Number(6, 0x7F); break;  // 8
  353.     }
  354. }

  355. // 清除所有顯示
  356. void Clear_Display()
  357. {
  358.     unsigned char i;
  359.     for(i = 1; i <= 8; i++)
  360.     {
  361.         MAX7219_WriteCmd(i, 0x00);
  362.     }
  363. }

復制代碼


評分

參與人數 1黑幣 +10 收起 理由
wpppmlah + 10 贊一個!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:39720 發表于 2026-5-3 08:14 | 只看該作者
我的壓縮文件怎么發呀?
回復

使用道具 舉報

板凳
ID:143767 發表于 2026-5-3 17:23 | 只看該作者
壓縮文件在哪里?
回復

使用道具 舉報

地板
ID:1064915 發表于 2026-5-4 08:10 | 只看該作者
MAX7219 是美國MAXIM 公司推出的多位LED 顯示驅動器,采用3 線串行接口傳送數據,可直接與單片機接口連接,用戶能方便修改其內部參數,以實現多位LED 顯示。它內含硬件動態掃描電路、BCD譯碼器、段驅動器和位驅動器。
回復

使用道具 舉報

5#
ID:477512 發表于 2026-5-5 08:01 | 只看該作者
壓縮文件在哪里?
回復

使用道具 舉報

6#
ID:262 發表于 2026-5-8 16:37 | 只看該作者
dingxizhang 發表于 2026-5-3 08:14
我的壓縮文件怎么發呀?

這里有方法:http://www.denmoz.com/bbs/dpj-134340-1.html
回復

使用道具 舉報

7#
ID:39720 發表于 2026-5-18 12:59 | 只看該作者
stc51單片機節拍器.rar (100.45 KB, 下載次數: 0)
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表