找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1893|回复: 1
打印 上一主题 下一主题
收起左侧

单片机控制的无线抢答器程序源码

[复制链接]
跳转到指定楼层
楼主
ID:74868 发表于 2018-8-2 16:40 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  1. #include <REG51.h>
  2. #include <STRING.H>

  3. /******************************************************************
  4. *    自定义Macro
  5. *******************************************************************/

  6. //编码的均为反向编码

  7. #define CLEAR 0x7f                  //定义清空的反码
  8. #define LED_BEGIN 0x01            // 定义开始时数码管的显示
  9. #define LED_FOUL 0x38             // 犯规后显示字母"F",数码管编码
  10. #define LED_C 0x31                // 字母"C"的编码
  11. #define LED_L 0x71                // 字母"L"的编码,两个用来在主持人取消之后显示"CL"--cancel
  12. #define GET 1                     // 这个是作为一个函数的参数来混的,就是成功抢答的意思
  13. #define FOUL 0                    // 和上面的参数一起混的,犯规---这两个的用法在后面体现
  14. #define READY 0x7e

  15. //下面是给上位机发送的指令,对应的是cmdID
  16. #define _STRING_READY_ 9//调整好抢答倒计时,准备开始抢答
  17. #define _STRING_START_ 8//读秒结束,抢答开始
  18. #define _STRING_CANCEL_ 7//取消抢答
  19. #define _CHANGE_TIME_ 6//每次读秒
  20. //发送1--4的指令代表抢答端的序号

  21. //因为在板子上面采用的是12M的晶振,仿真时候采用的是11.0529M的晶振,为了方便不同时候编译方便,这里与后面的条件编译一起使程序修改参数比较方便
  22. //#define CLOCK_FREQUENCY_12M 1

  23. /******************************************************************
  24. *    自定义数据类型
  25. *******************************************************************/
  26. typedef unsigned char Byte;       // 一个字节
  27. typedef unsigned int Word;        // 一个字,两个字节
  28. typedef bit Bool;                 // 模仿布尔型变量
  29. //typedef sbit Port;              // 本想用自定义一个端口类型的变量,比较方便,但是这句话步知道为何通不过编译

  30. /******************************************************************
  31. *    定义MAX7219寄存器
  32. *******************************************************************/
  33. #define REG_NO_OP 0x00        // 定义空操作 register
  34. #define DIG_1 0x01            // 定义数码管1 register
  35. #define DIG_2 0x02            // 定义数码管2 register
  36. #define DIG_3 0x03            // 定义数码管3 register
  37. #define DIG_4 0x04            // 定义数码管4 register
  38. #define DIG_5 0x05            // 定义数码管5 register
  39. #define DIG_6 0x06            // 定义数码管6 register
  40. #define DIG_7 0x07            // 定义数码管7 register
  41. #define DIG_8 0x08            // 定义数码管8 register
  42. #define REG_DECODE 0x09       // 定义解码控制 register
  43. #define REG_INTENSITY 0x0a    // 定义显示亮度 register
  44. #define REG_SCAN_LIMIT 0x0b   // 定义扫描限制 register
  45. #define REG_SHUTDOWN 0x0c     // 定义"shutdown"模式 register
  46. #define REG_DISPLAY_TEST 0x0f // 定义"display test"模式 register
  47. #define INTENSITY_MIN 0x00    // 定义最低显示亮度
  48. #define INTENSITY_MAX 0x0f    // 定义最高显示亮度

  49. /*********************************************************************
  50. *    定义硬件引脚连接
  51. **********************************************************************/
  52. sbit DATA=P2^0;               // MAX7219的数据口
  53. sbit LOAD=P2^1;               // MAX7219的锁存端口
  54. sbit CLK=P2^2;                // MAX7219的时钟端口

  55. sbit HOST_START=P0^0;             //主持人按键,用来重新开始的按键    start
  56. sbit HOST_CANCEL=P0^1;            //主持人用来取消抢答的按键        clear

  57. sbit SWITCH1_3=P1^4;    // 调节倒计时时间的拨码开关,下划线前面的号代表开关的序号,下划线后面的号代表该开关的数值
  58. sbit SWITCH2_2=P1^5;          // 同上
  59. sbit SWITCH3_2=P1^6;          // 同上
  60. sbit SWITCH4_1=P1^7;          // 同上

  61. sbit BEEP=P0^7;            //定义蜂鸣器端口

  62. #ifdef USE_SOUND       //可以通过define来选择要不要使用仿真时候的声音
  63. sbit LS138_C=P2^4;       //定义译码器输入端
  64. sbit LS138_B=P2^5;       //同上                  
  65. sbit LS138_A=P2^6;       //同上
  66. sbit LS138_E1=P2^7;       //定义译码器使能端
  67. #endif

  68. /*********************************************************************
  69. *    定义全局变量
  70. **********************************************************************/
  71. Byte data intrCounter; // 计时器中断次数
  72. Byte data beginNum;    // 开始倒计时的时间
  73. Byte data counterBack;  // 将中断次数放在里面以备后用
  74. Byte data showNum;     // 数码管正在显示的时间
  75. Bool data isStart;     // 是否开始抢答  
  76. Bool data isFoul;      // 是否犯规
  77. Bool data isPressed;   // 是否有抢答的键按下
  78. Byte data number_temp; // 用来记录P1口上次状态的一个变量
  79. Bool data needResetTimes;//记录是否需要重设Timer0的溢出次数

  80. code unsigned char C51BOX2[3] _at_ 0x43; //使用C51Box时候防止程序跑丢

  81. /***********************************************************************
  82. *   共阴极七段数码管显示对应段查询表(数字0-9分别对应code_table[0]-[9])
  83. ***********************************************************************/
  84. Byte code code_table_zheng[10]=
  85. {0x7e,0x30,0x6d,0x79,0x33,0x5b,0x5f,0x70,0x7f,0x7b};

  86. Byte code code_table[10]=
  87. {0x01,0x4f,0x12,0x06,0x4c,0x24,0x20,0x0f,0x00,0x04};

  88. /***********************************************************************
  89. *   函数声明
  90. ***********************************************************************/
  91. void MAX7219_SendByte (Byte dataout);
  92. void MAX7219_Write (Byte reg_number, Byte dataout);
  93. void MAX7219_DisplayChar(Byte digit, Byte character);
  94. void MAX7219_Clear (void);
  95. void MAX7219_SetBrightness (Byte brightness);
  96. void MAX7219_DisplayTestStart (void);
  97. void MAX7219_DisplayTestStop (void);
  98. void MAX7219_ShutdownStart (void);
  99. void MAX7219_ShutdownStop (void);
  100. void MAX7219_Init (void);
  101. void Delay10ms(void);
  102. Bool GetHostStartKey (void);
  103. Bool GetHostCancelKey (void);
  104. void GetCounter(void);
  105. Byte GetPressed(Byte KeyState);
  106. Byte GetPressedWireless(Byte KeyState);
  107. void IT0_Init(void);
  108. void Timer0_Overflow();
  109. void PressedHandle(Byte keyPressed);
  110. void GetOrFoulHandle(Bool state);
  111. void CancelHandle();
  112. void SPEAKER_count (void);    //声明倒计时声音函数
  113. void SPEAKER_start(void);        //声明开始抢答声音函数
  114. void SPEAKER_get(void);    //声明抢到声音函数
  115. void SPEAKER_foul(void);   //  声明犯规声音函数
  116. void initialSerial();
  117. void sendNumber(int number);//串口发送数字,这里发送的是CommandID
  118. void sendString(unsigned char *string);//串口发送字符串

  119. /***********************************************************************
  120. * MAX7219_SendByte()
  121. *
  122. * 描述: 向MAX7219传送一个字节的数据
  123. * Arguments : dataout = data to send
  124. * Returns : none
  125. *************************************************************************/
  126. void MAX7219_SendByte (Byte dataout)
  127. {
  128.     Byte i;
  129.     for (i=8;i>0;i--)
  130.     {
  131.         Byte mask=1<<(i-1);//mask是个掩码,取位使用
  132.         CLK=0;//MAX7219的位传入是在时钟的上升沿之前,所以在每发一位之前都要变为低电平
  133.         if (dataout&mask)
  134.             DATA=1;
  135.         else
  136.             DATA=0;
  137.         CLK=1;//八个bit都传递完成后变为高电平,锁存
  138.     }
  139. }

  140. /***********************************************************************
  141. * MAX7219_Write()
  142. *
  143. * 描述: 向 MAX7219 写命令
  144. * Arguments : reg_number = register to write to
  145. * dataout = data to write to MAX7219
  146. * Returns : none
  147. 未完~
  148. ***************************************************************************/
  149. void MAX7219_Write (Byte reg_number, Byte dataout)
  150. {
  151.         LOAD=0;//也是锁存上升沿之前的,发这两个字节之前要变为低电平
  152.         MAX7219_SendByte(reg_number);//发送寄存器地址
  153.         MAX7219_SendByte(dataout);//发送数据
  154.         LOAD=1;//变为高电平,锁存
  155. }

  156. /**************************************************************************
  157. * MAX7219_DisplayChar()
  158. *
  159. * 描述: 使某一位显示一个数字
  160. * Arguments : digit = digit number (0-7)
  161. * character = character to display (0-9, A-Z)
  162. * Returns : none
  163. **************************************************************************/
  164. void MAX7219_DisplayChar(Byte digit, Byte character)
  165. {
  166.          MAX7219_Write(digit, character);
  167. }

  168. /**************************************************************************
  169. * MAX7219_Clear()
  170. *
  171. * 描述: 清除所有位的显示
  172. * Arguments : none
  173. * Returns : none
  174. ***************************************************************************/
  175. void MAX7219_Clear (void)
  176. {
  177.          Byte i;
  178.          for (i=1; i<=2; i++)
  179.          MAX7219_Write(i, CLEAR);//把八个数码管全都清零了,已经写反了^_^
  180. }

  181. /**************************************************************************
  182. * MAX7219_SetBrightness()
  183. *
  184. * 描述: 设置数码管显示亮度
  185. * Arguments : brightness (0-15)
  186. * Returns : none
  187. ***************************************************************************/
  188. void MAX7219_SetBrightness (Byte brightness)
  189. {
  190.          brightness &= 0x0f;
  191.          MAX7219_Write(REG_INTENSITY, brightness);
  192. }

  193. /**************************************************************************
  194. * MAX7219_DisplayTestStart()
  195. *
  196. * 描述: 进入 test 模式
  197. * Arguments : none
  198. * Returns : none
  199. ***************************************************************************/
  200. void MAX7219_DisplayTestStart (void)
  201. {
  202.     MAX7219_Write(REG_DISPLAY_TEST, 1);
  203. }

  204. /**************************************************************************
  205. * MAX7219_DisplayTestStop()
  206. *
  207. * 描述: 退出 test 模式
  208. * Arguments : none
  209. * Returns : none
  210. ***************************************************************************/
  211. void MAX7219_DisplayTestStop (void)
  212. {
  213.     MAX7219_Write(REG_DISPLAY_TEST, 0);
  214. }

  215. /**************************************************************************
  216. * MAX7219_ShutdownStart()
  217. *
  218. * 描述: 进入 shutdown 模式
  219. * Arguments : none
  220. * Returns : none
  221. ***************************************************************************/
  222. void MAX7219_ShutdownStart (void)
  223. {
  224.     MAX7219_Write(REG_SHUTDOWN, 0);
  225. }

  226. /**************************************************************************
  227. * MAX7219_ShutdownStop()
  228. *
  229. * 描述: 退出 shutdown 模式
  230. * Arguments : none
  231. * Returns : none
  232. ***************************************************************************/
  233. void MAX7219_ShutdownStop (void)
  234. {
  235.         MAX7219_Write(REG_SHUTDOWN, 1);
  236. }

  237. /**************************************************************************
  238. * MAX7219_Init()
  239. *
  240. * Description: MAX7219初始化模块; 应该先于其他MAX7219函数而被调用
  241. * Arguments : none
  242. * Returns : none
  243. ***************************************************************************/
  244. void MAX7219_Init (void)
  245. {
  246.     DATA=1;
  247.     CLK=1;
  248.     LOAD=1;
  249.     MAX7219_Write(REG_SCAN_LIMIT,1);//这里设置的是扫描两个数码管
  250.     MAX7219_Write(REG_DECODE, 0x00);
  251.     MAX7219_SetBrightness(INTENSITY_MAX);//设置最大亮度显示
  252.     MAX7219_DisplayTestStart();
  253.     MAX7219_DisplayTestStop();
  254.     MAX7219_ShutdownStop();
  255.     MAX7219_Clear();
  256. }

  257. /**************************************************************************
  258. * Delay_100us()
  259. *
  260. * 描述: 延时100us,主要用在消除开关抖动时
  261. * Arguments : none
  262. * Returns : none
  263. ***************************************************************************/
  264. void Delay10ms(void)
  265. {
  266. unsigned char i,j;
  267. for(i=20;i>0;i--)
  268. for(j=248;j>0;j--);
  269. }
  270. /**************************************************************************
  271. * GetHostStartKey()
  272. *
  273. * Description: 取得主持人开始按键的键值
  274. * Arguments : none
  275. * Returns : 1-->主持人按键; 0-->主持人未按键
  276. ***************************************************************************/
  277. Bool GetHostStartKey (void)
  278. {
  279.     if (HOST_START ==1)
  280.         return 0;
  281.     else
  282.         Delay10ms ();//如果发现主持人按键接通,要先延时100us,防止抖动
  283.     if (HOST_START==1)
  284.         return 0;
  285.     else
  286.         return 1;//延时时候还是接通,则判断为该键确实按下   
  287. }

  288. /**************************************************************************
  289. * GetHostCancelKey()
  290. *
  291. * Description: 取得主持人取消按键的键值
  292. * Arguments : none
  293. * Returns : 1-->主持人按键; 0-->主持人未按键
  294. ***************************************************************************/
  295. Bool GetHostCancelKey (void)
  296. {
  297.     if (HOST_CANCEL ==1)
  298.         return 0;
  299.     else
  300.         Delay10ms ();//如果发现主持人按键接通,要先延时100us,防止抖动
  301.     if (HOST_CANCEL ==1)
  302.         return 0;
  303.     else
  304.         return 1;//延时时候还是接通,则判断为该键确实按下   
  305. }

  306. /**************************************************************************
  307. * GetCounter
  308. *
  309. * Description: 取得预先设置的倒计时时间
  310. * Arguments : none
  311. * Returns : none
  312. ***************************************************************************/
  313. void GetCounter(void)
  314. {
  315.     beginNum=1;//在所有开关都没有拨动的时候倒计时为1秒,比设置为0秒要好
  316.     intrCounter=20;//每一秒对应的中断次数为20次
  317.     if (SWITCH1_3==1)
  318.     {
  319.         beginNum+=3;
  320.     }
  321.     if (SWITCH2_2==1)
  322.     {
  323.         beginNum+=2;
  324.     }
  325.     if (SWITCH3_2==1)
  326.     {
  327.         beginNum+=2;
  328.     }
  329.     if (SWITCH4_1==1)
  330.     {
  331.         beginNum+=1;
  332.     }//以上判断语句为判断拨码开关状态
  333.     intrCounter=20*beginNum;//计算总扫描次数
  334. }

  335. /**************************************************************************
  336. * GetPressed
  337. *
  338. * Description: 从P2口连接抢答端的四位来判断抢答情况
  339. * Arguments : Byte KeyState-->P2 state
  340. * Returns : 抢答端的号码 ; 0-->没人抢答
  341. ***************************************************************************/
  342. Byte GetPressed(Byte KeyState)
  343. {
  344.     Byte key;//记录抢答端的号码
  345.     KeyState&=0xf0;//取P1口的低四位

  346.     switch (KeyState)
  347.     {
  348.         case 0xf0: key=0;break;//全高,无人抢答
  349.         case 0xe0: key=1;break;//只有P1.1,key1抢答
  350.         case 0xd0: key=2;break;//只有P1.2,key2抢答
  351.         case 0xb0: key=3;break;//只有P1.3,key3抢答
  352.         case 0x70: key=4;break;//只有P1.4,key4抢答
  353.     }
  354.     /*
  355.     switch (KeyState)
  356.     {
  357.         case 0x00: key=0;break;//全高,无人抢答
  358.         case 0x01: key=1;break;//只有P1.0,key1抢答
  359.         case 0x02: key=2;break;//只有P1.1,key2抢答
  360.         case 0x04: key=3;break;//只有P1.2,key3抢答
  361.         case 0x08: key=4;break;//只有P1.3,key4抢答
  362.     }
  363.     */
  364.     //上面是在用高电平来判断抢答状态时的程序,经证明不知道为何无效

  365.     return key;   
  366. }

  367. /**************************************************************************
  368. * GetPressedWireless
  369. *
  370. * Description: P2口的高四位于Pt2272接受模块相连,该方法用来判断无线抢答序号
  371. * Arguments : Byte KeyState-->P2 state
  372. * Returns : 抢答端的号码 ; 0-->没人抢答
  373. ***************************************************************************/
  374. Byte GetPressedWireless(Byte KeyState)
  375. {
  376.     Byte key;//记录抢答端的号码
  377.     KeyState&=0xf0;//取P2口的高四位

  378.     /*
  379.     switch (KeyState)
  380.     {
  381.         case 0x0f: key=0;break;//全高,无人抢答
  382.         case 0x0e: key=1;break;//只有P1.1,key1抢答
  383.         case 0x0d: key=2;break;//只有P1.2,key2抢答
  384.         case 0x0b: key=3;break;//只有P1.3,key3抢答
  385.         case 0x07: key=4;break;//只有P1.4,key4抢答
  386.     }
  387.     */

  388.     switch (KeyState)
  389.     {
  390.         case 0x00: key=0;break;//全低,无人抢答
  391.         case 0x10: key=1;break;//只有P1.0,key1抢答
  392.         case 0x20: key=2;break;//只有P1.1,key2抢答
  393.         case 0x40: key=3;break;//只有P1.2,key3抢答
  394.         case 0x80: key=4;break;//只有P1.3,key4抢答
  395.     }
  396.     return key;   
  397. }

  398. /**************************************************************************
  399. * IT0_Init
  400. *
  401. * Description: 初始化计时器T0的状态
  402. * Arguments : none
  403. * Returns : none
  404. ***************************************************************************/
  405. void IT0_Init(void)
  406. {
  407.     TMOD=0x21;//设置T0在方式1下工作,同时还要保证T1,也就是波特率所学的定时器的正常工作

  408.     #ifdef CLOCK_FREQUENCY_12M//对使用哪种晶振进行条件编译
  409.     TH0=0x3C;//12M晶振时的装入值
  410.     TL0=0xAF;
  411.     #else
  412.     TH0=0x4C;//11.0529M晶振时装入值
  413.     TL0=0x00;
  414.     #endif

  415.     ET0=1;//使T0中断可以溢出
  416.     EA=1;//开启总中断
  417.     TF0=0;//溢出位清零
  418.     TR0=1;//开启T0
  419. }

  420. /**************************************************************************
  421. * Timer0_Overflow() interrupt 1
  422. *
  423. * Description: 中断溢出服务程序, 采用的是中断方式1, 后面最好不加using选择寄存器组以免与系统用在主程序的寄存器冲突
  424. * Arguments : none
  425. * Returns : none
  426. ***************************************************************************/
  427. void Timer0_Overflow() interrupt 1
  428. {
  429.     static Byte times=20;//溢出次数,用20次中断来判断1秒
  430.     //这里存在重大bug,到由于有相应而停止Timer0后,再次启用时,这里的second没有回归原值

  431.     if (needResetTimes==1)
  432.     {
  433.         times=20;
  434.         needResetTimes=0;//已重设,不需要再次重新设置溢出次数
  435.     }

  436.     #ifdef CLOCK_FREQUENCY_12M//对使用哪种晶振进行条件编译
  437.     TH0=0x3C;//12M晶振时的装入值
  438.     TL0=0xAF;//这两个寄存器存的是计数器的计数开始的值,计算发现这两个值累加至溢出后正好是50ms
  439.     #else
  440.     TH0=0x4C;//11.0529M晶振时装入值
  441.     TL0=0x00;//同理,这两个寄存器存的是计数器的计数开始的值,计算发现这两个值累加至溢出后正好是50ms
  442.     #endif

  443.     times--;
  444.     intrCounter--;

  445.     /* 原来使用的方法
  446.     if (times==0)//每隔一秒的操作
  447.     {
  448.         MAX7219_DisplayChar(DIG_2,code_table[--showNum]); //要避免用上面的会造成显示"0"后面一秒钟,才进入开始
  449.         times=20;//重新赋值每秒计数器
  450.         if (intrCounter==0)
  451.         {
  452.             TR0=0;//关闭T0计数器
  453.             isStart=1;//计时结束,进入正常抢答
  454.             //SPEAKER_start();//开始抢答的声音
  455.         }
  456.         //待显示"0"以后就开始抢答
  457.         else
  458.         {
  459.             //SPEAKER_count();//倒计时声音        
  460.         }
  461.     }
  462.     */

  463.     if (times==0)//每隔一秒的操作
  464.     {
  465.         //if (showNum!=1) SPEAKER_count();//倒计时声音
  466.         //else SPEAKER_start();//开始抢答的声音
  467.         MAX7219_DisplayChar(DIG_2,code_table[--showNum]);//显示数字
  468.         sendNumber(_CHANGE_TIME_);//给上位机发送要显示数字的命令
  469.         times=20;//重新赋值每秒计数器
  470.      }//待显示"0"以后就开始抢答

  471.      if (intrCounter==0)
  472.      {
  473.         TR0=0;//关闭T0计数器
  474.         isStart=1;//计时结束,进入正常抢答
  475.      }

  476. }

  477. /**************************************************************************
  478. * PressedHandle
  479. *
  480. * Description: 按键处理
  481. * Arguments : Byte keyPressed-->按下的按键
  482. * Returns : none
  483. ***************************************************************************/
  484. void PressedHandle(Byte keyPressed)
  485. {
  486.     MAX7219_Clear();//LED clear
  487.     MAX7219_DisplayChar(DIG_2,code_table[keyPressed]);//在右侧数码管显示抢答选手号码,此时没有去判断是否犯规

  488.     //给上位机发抢答选手的号码
  489.     sendNumber(keyPressed);
  490. }

  491. /**************************************************************************
  492. * GetOrFoulHandle(Bool state)
  493. *
  494. * Description: 正常抢答或是犯规处理
  495. * Arguments : Bool state-->是GET和FOUL两个宏的取之之一
  496. * Returns : none
  497. ***************************************************************************/
  498. void GetOrFoulHandle(Bool state)
  499. {
  500.     if (!state)
  501.     {
  502.         MAX7219_DisplayChar(DIG_1,LED_FOUL);//如果是犯规的话左边的LED要显示"F",foul
  503.     }
  504. }

  505. /**************************************************************************
  506. * CancelHandle()
  507. *
  508. * Description: 处理主持人取消倒计时
  509. * Arguments : none
  510. * Returns : none
  511. ***************************************************************************/
  512. void CancelHandle()
  513. {   
  514.     MAX7219_DisplayChar(DIG_1,LED_C);
  515.     MAX7219_DisplayChar(DIG_2,LED_L);//主持人取消倒计时之后,两个数码管显示"CL"-->cancel
  516. }

  517. /**************************************************************************
  518. * delayus()
  519. *
  520. * Description: 延时程序
  521. * Arguments : t-->us
  522. * Returns : time delayed
  523. ***************************************************************************/
  524. void delayus(unsigned char t )
  525. {
  526.      unsigned char j;
  527.     for(;t>0;t--)
  528.         for(j=19;j>0;j--);
  529. }

  530. /**************************************************************************
  531. * SPEAKER_count/start/foul/get()
  532. *
  533. * Description: speaker发声程序->计数/开始/犯规/抢答 四种声音
  534. * Arguments : none
  535. * Returns : none
  536. ***************************************************************************/
  537. void SPEAKER_count(void)
  538. {
  539.     unsigned char i;
  540.     for    (i=0;i<10;i++)
  541.     {
  542.         BEEP =1; //点亮
  543.         delayus(20);
  544.         BEEP =0; //熄灭   
  545.         delayus(20);
  546.      }
  547. }

  548. void  SPEAKER_start(void)
  549. {
  550.     unsigned char i;
  551.     for(i=0;i<200;i++)
  552.     {
  553.           BEEP =1; //点亮
  554.         delayus(10);
  555.         BEEP =0; //熄灭   
  556.         delayus(10);
  557.     }
  558. }

  559. void  SPEAKER_foul(void)
  560. {
  561.     unsigned char i;
  562.     for(i=0;i<250;i++)
  563.     {
  564.           BEEP =1; //点亮
  565.         delayus(15);
  566.         BEEP =0; //熄灭   
  567.         delayus(17);
  568.     }

  569. }

  570. void  SPEAKER_get(void)
  571. {
  572.     unsigned char i;
  573.     for(i=0;i<250;i++)
  574.     {
  575.           BEEP =1; //点亮
  576.         delayus(10);
  577.         BEEP =0; //熄灭   
  578.         delayus(10);
  579.     }

  580.     for(i=0;i<250;i++)
  581.     {
  582.           BEEP =1; //点亮
  583.         delayus(20);
  584.         BEEP =0; //熄灭   
  585.         delayus(20);
  586.     }
  587. }

  588. /**************************************************************************
  589. * initialSerial()
  590. *
  591. * Description: 初始化串口
  592. * Arguments : none
  593. * Returns : none
  594. ***************************************************************************/
  595. void initialSerial()
  596. {
  597.     EA=0;//关闭所有中断
  598.     TMOD=0x21;//设置T1定时器的工作模式:方式2;同时保证T0的工作模式正常.这儿太重要了
  599.     TH1=0xFA;
  600.     TL1=0xFA;
  601.     PCON=0x80;//设置SMOD=1
  602.     SCON=0x50;//选择工作方式1,即为UART
  603.     TR1=1;//设置好定时器并打开定时器,定好波特率9600bit/s
  604. }

  605. /**************************************************************************
  606. * sendNumber(int number)
  607. *
  608. * Description: 通过串口发送一位数字
  609. * Arguments : number->要发送的数字
  610. * Returns : none
  611. ***************************************************************************/
  612. void sendNumber(int number)
  613. {
  614.     TI=0;
  615.     SBUF=number+48;
  616.     while(!TI);
  617.     TI=0;
  618. }

  619. /**************************************************************************
  620. * sendString(unsigned char *string)
  621. *
  622. * Description: 通过串口发送字符串
  623. * Arguments : 要发送的字符串的头指针
  624. * Returns : none
  625. ***************************************************************************/
  626. void sendString(unsigned char *string)
  627. {
  628.     do
  629.     {
  630.         SBUF=*string;
  631.         while(!TI);
  632.         TI=0;
  633.         string++;
  634.     }while(*(string-1)!='\0');

  635. /**************************************************************************
  636. * 主程序
  637. ***************************************************************************/
  638. void main()
  639. {   
  640.     //P1=0xff;
  641.     Byte keyPressed,i;//选手按键号码,没有的话为0   
  642.     Bool hostPressed;//用来记录主持人按键取消,0为没有动作,1为取消
  643.     Byte buf[10];//设置发送缓冲区
  644.     number_temp=P1&0xf0;//P1口上次的状态,在调整倒计时时间的时候用到的   

  645.     #ifdef USE_SOUND
  646.     LS138_E1=1;         //译码器初始化
  647.     #endif

  648.     needResetTimes=0;//不需要重新设置溢出次数

  649.     MAX7219_Init();//数码管初始化
  650.     initialSerial();//初始化串口发送

  651.     GetCounter();//获取开始时候设置的倒计时时间   
  652.     MAX7219_DisplayChar(DIG_1,code_table[beginNum]);
  653. //显示开始时设置的倒计时时间,在左位设置     
  654.     MAX7219_DisplayChar(DIG_2,READY);//调时间的时候右位的显示

  655.     while(GetHostStartKey()==0)//当主持人没有按键的时候进入循环
  656.     {
  657.         if (number_temp!=(P1&0xf0))
  658. //若调整了倒计时时间,则P1口状态变了,就要重新设置和显示
  659.         {
  660.             GetCounter();//获取调整以后的倒计时时间
  661.             MAX7219_DisplayChar(DIG_1,code_table[beginNum]);
  662. //显示调整以后的倒计时时间
  663.             number_temp=P1&0xf0;//记录下来现在P1口的状态,以备后面的比较
  664.         }            
  665.     }    //当主持人按键以后就结束调整进入抢答倒计时
  666.     sendNumber(beginNum);

  667.     MAX7219_DisplayChar(DIG_1,READY);
  668.     while(GetHostCancelKey()==0);

  669.     sendNumber(_STRING_READY_);//发送调节完毕准备抢答的命令;

  670.     //调整好倒计时时间后,按下start显示"--",再按下cancel则显示倒计时时间,此时可以开始倒计时了.
  671.     MAX7219_DisplayChar(DIG_1,READY);//清空右边一位数码管
  672.     MAX7219_DisplayChar(DIG_2,code_table[beginNum]);
  673.     for (i=100;i--;i>0)
  674.         Delay10ms();//防止后面出现连读的情况..

  675.     counterBack=intrCounter; //备份要中断的总次数
  676.     while(1)//这里要用自己加的循环来把程序束缚在这里运行
  677.     {
  678.         showNum=beginNum;//设置要显示的时间,当然时从倒计时时间开始
  679.         intrCounter=counterBack;//设置总中断的次数
  680.         TR0=0;//禁用计时器0
  681.         isPressed=0;//记录是否有人按键
  682.         isStart=0;//没有开始抢答
  683.         while(GetHostStartKey()==0);

  684.         //给上位机发送开始倒计时的指令
  685.         sendNumber(_STRING_START_);

  686.         needResetTimes=1;//Timer0已经是第二轮开始,需要重新设置溢出次数
  687.         IT0_Init();//初始化计时器0, 启用.

  688.         MAX7219_DisplayChar(DIG_1,CLEAR);//清空左边一位数码管
  689.         while(!isPressed)//如果没有记录到有人按键就进入
  690.         {
  691.             keyPressed=GetPressed(P2);
  692. //查询一下P2口的状态,即按键情况,P2口的后四位作为抢答端输入,有线时候使用
  693.             //keyPressed=GetPressedWireless(P2);//查询一下P2口的状态,即按键情况,无线使用
  694.             hostPressed=GetHostCancelKey();
  695.             if (!keyPressed&&!hostPressed)//如果没有人按键,就进入下次循环
  696.                 continue;
  697.             else
  698.             {
  699.                 TR0=0;//关闭定时器
  700.                 isPressed=1;//记录到有人按键,提供条件跳出循环
  701.             }
  702.         }

  703.         if (keyPressed!=0)
  704.         {
  705.             if (isStart)//如果已经开始抢答
  706.             {
  707.                 PressedHandle(keyPressed);//处理按键,即显示抢答选手号码
  708.                 GetOrFoulHandle(GET);//处理抢答

  709.                 #ifdef USE_SOUND//对是否使用扬声器进行条件编译
  710.                 LS138_E1=0;       //译码器准备工作
  711.                 switch (keyPressed)
  712.                 {
  713.                     case 1:      LS138_A=0;LS138_B=0;LS138_C=0;break;       //1号成功灯亮
  714.                     case 2:      LS138_A=0;LS138_B=1;LS138_C=0;break;       //2号成功灯亮
  715.                     case 3:  LS138_A=1;LS138_B=0;LS138_C=0;break;       //3号成功灯亮
  716.                     case 4:  LS138_A=1;LS138_B=1;LS138_C=0;break;       //4号成功灯亮
  717.                     default : break;
  718.                 }
  719.                 #endif
  720.             }   

  721.             else//否则,没有开始抢答
  722.             {   
  723.                 PressedHandle(keyPressed);//处理按键,即显示抢答选手号码
  724.                 GetOrFoulHandle(FOUL);//处理犯规,必须要放在后面,因为显示数字的里面有一个clear

  725.                 #ifdef USE_SOUND//对是否使用扬声器进行条件编译
  726.                 LS138_E1=0;       //译码器准备工作
  727.                 switch (keyPressed)
  728.                 {
  729.                     case 1: LS138_A=0;LS138_B=0;LS138_C=1;break;                                       //1号犯规灯亮
  730.                     case 2:  LS138_A=0;LS138_B=1;LS138_C=1;break;       //2号犯规灯亮
  731.                     case 3:  LS138_A=1;LS138_B=0;LS138_C=1;break;       //3号犯规灯亮
  732.                     case 4:  LS138_A=1;LS138_B=1;LS138_C=1;break;       //4号犯规灯亮
  733.                     default : break;
  734.                 }
  735.                 #endif
  736.             }
  737.         }

  738.         if (hostPressed==1)
  739.         {
  740.             CancelHandle();
  741.             //向上位机发送主持人取消的指令
  742.             sendNumber(_STRING_CANCEL_);
  743.             for (i=100;i--;i>0)
  744.                 Delay10ms();//防止后面出现连读的情况..        
  745.         }
  746.         while(GetHostCancelKey()==0);//如果主持人没有按键再次开始,则停在次死循环处

  747.         #ifdef USE_SOUND//对是否使用扬声器进行条件编译
  748.         LS138_E1=1;        //关闭译码器
  749.         #endif

  750.         MAX7219_DisplayChar(DIG_1,READY);//清空右边一位数码管
  751.         MAX7219_DisplayChar(DIG_2,code_table[beginNum]);//左位显示设置的倒计时时间

  752.         //给上位机发送重新开始倒计时的指令
  753.         sendNumber(_STRING_READY_);


复制代码


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:1 发表于 2018-8-2 16:47 | 只看该作者
需要补全原理图才可获得积分
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表