找回密码
 立即注册
楼主: 芯希望

《8051U深度入门到32位51大型实战教学视频》学习心路历程

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:9
  • 最近打卡:2025-04-30 11:37:57
已绑定手机

6

主题

33

回帖

280

积分

版主

积分
280
发表于 2025-1-22 11:50:30 | 显示全部楼层
第13集外部中断,已手敲代码,测试通过。

任务一:当按下外部中断INT1/P33,P01的LED改变原来的状态

截图202501221142407565.jpg


  1. #include "io.h"
  2. u8 State1 = 0;                                        //LED1初始状态
  3. u8 State2 = 0;                                        //LED2初始状态
  4. u8 State3 = 0;                                        //LED3初始状态
  5. u16 Key_Vol ;                                //按键按下持续时间
  6. u8 SEG_NUM[]=
  7. {
  8.     0x3F,       /*'0', 0*/
  9.     0x06,       /*'1', 1*/
  10.     0x5B,       /*'2', 2*/
  11.     0x4F,       /*'3', 3*/
  12.     0x66,       /*'4', 4*/
  13.     0x6D,       /*'5', 5*/
  14.     0x7D,       /*'6', 6*/
  15.     0x07,       /*'7', 7*/
  16.     0x7F,       /*'8', 8*/
  17.     0x6F,       /*'9', 9*/
  18.     0x77,       /*'A', 10*/
  19.     0x7C,       /*'B', 11*/
  20.     0x39,       /*'C', 12*/
  21.     0x5E,       /*'D', 13*/
  22.     0x79,       /*'E', 14*/
  23.     0x71,       /*'F', 15*/
  24.     0x40,       /*'-', 16*/
  25.     0x00,       /*' ', 17*/
  26.     0x80,       /*'.', 18*/
  27. };
  28. u8 T_NUM[8] =
  29. {
  30.         0X01,0X02,0X04,0X08,0X10,0X20,0X40,0X80
  31. };
  32. void LED0_Blink(void)
  33. {
  34.         State1 = !State1;
  35.         P00 = State1;
  36. }
  37. void LED1_Blink(void)
  38. {
  39.         State2 = !State2;
  40.         P01 = State2;
  41. }
  42. void LED2_Blink(void)
  43. {
  44.         State3 = !State3;
  45.         P02 = State3;
  46. }
  47. void KEY_Task(void)
  48. {
  49.         if( P33 == 0 )
  50.         {
  51.                 Key_Vol++;
  52.                 if( Key_Vol==5 )
  53.                 {
  54.                         //按键按下的任务
  55. //                        printf( "按键单击\r\n" );
  56.                         
  57.                         USB_Reset_U();
  58.                         
  59.                         IAP_CONTR = 0X20;
  60.                 }
  61.         }
  62.         else
  63.         {
  64.                 Key_Vol = 0;
  65.         }
  66.         
  67. }
  68. /*
  69.         #define ROW1        P06                        //端口定义
  70.         #define ROW2        P07
  71.         #define COL1        P00
  72.         #define COL2        P01
  73.         #define COL3        P02
  74.         #define COL4        P03
  75. */
  76. u8 key_num = 0xff;
  77. //任务1:数码管显示当前的按键号
  78. void Task_1(void)
  79. {
  80.         //①第一步:现将P0.0-P0.3输出低电平,P0.6-P0.7输出高电平,如果有按键按下,按下的那一行的IO就会变成低电平,就可以判断出哪一行按下了。
  81.         COL1 = 0;
  82.         COL2 = 0;
  83.         COL3 = 0;
  84.         COL4 = 0;
  85.         ROW1 = 1;
  86.         ROW2 = 1;
  87.         
  88.         if(( ROW1 == 0 ) || ( ROW2 == 0 ))                //如果行按键有按下
  89.         {
  90.                 if(( ROW1 ==0 ) && ( ROW2 ==0 ))        //如果两行都有按键按下,不处理
  91.                 {
  92.                         
  93.                 }
  94.                 else if((( ROW1 ==1 )&&( ROW2 ==0 )) || (( ROW1 ==0 )&&( ROW2 ==1 )))        //如果有按键按下,而且只有一颗
  95.                 {
  96.                         if( ROW1 ==0 )                                //判断哪一行,输出行开始的序号
  97.                                 key_num = 0;
  98.                         else if( ROW2 ==0 )
  99.                                 key_num = 4;
  100.                                 
  101.                         //②第二步:现将P0.0-P0.3输出高电平,P0.6-P0.7输出低电平,如果有按键按下,按下的那一列的IO就会变成低电平,就可以判断出哪一列按下了。
  102.                         COL1 = 1;
  103.                         COL2 = 1;
  104.                         COL3 = 1;
  105.                         COL4 = 1;
  106.                         ROW1 = 0;
  107.                         ROW2 = 0;
  108.                         
  109.                         if( COL1 ==0 )                                //判断哪一列,叠加按键的序号
  110.                         {
  111. //                                key_num = key_num ;
  112.                         }
  113.                         else if( COL2 ==0 )
  114.                         {
  115.                                 key_num = key_num + 1;
  116.                         }
  117.                         else if( COL3 ==0 )
  118.                         {
  119.                                 key_num = key_num + 2;
  120.                         }
  121.                         else if( COL4 ==0 )
  122.                         {
  123.                                 key_num = key_num + 3;
  124.                         }
  125.                 }
  126.                 COL1 = 0;
  127.                 COL2 = 0;
  128.                 COL3 = 0;
  129.                 COL4 = 0;
  130.                 ROW1 = 1;
  131.                 ROW2 = 1;               
  132.         }
  133.         else
  134.         {
  135.                 key_num = 0xff;
  136.         }
  137.         
  138.         //③第三步:行列组合一下就可以判断出是哪个按键按下了。
  139. }
  140. void Init_595(void)
  141. {
  142.         HC595_SER = 0;
  143.         HC595_RCK = 0;
  144.         HC595_SCK = 0;        
  145. }
  146.         
  147. void Send_595( u8 dat )
  148. {
  149.         u8 i;
  150.         
  151.         for( i=0;i<8;i++ )
  152.         {
  153.                 dat <<= 1;                                //DAT = (DAT<<1);        //CY
  154.                 HC595_SER = CY;                //先把数据写到引脚上
  155.                 HC595_SCK = 1;                        //输出上升沿的时钟信号
  156.                 HC595_SCK = 0;
  157.         }
  158. }
  159. void Display_Seg(u8 HC595_1,u8 HC595_2)
  160. {
  161.         Send_595(HC595_1);                        //数码管段码输出  高电平点亮
  162.         Send_595(HC595_2);                        //数码管位码      低电平点亮
  163.         
  164.         HC595_RCK = 1;                                //数据输出        
  165.         HC595_RCK = 0;
  166. }
  167. //void SEG_Task(void)
  168. //{
  169. //        if( key_num == 255 )
  170. //                Display_Seg( SEG_NUM[17] , ~T_NUM[0]);                //数码管刷段码和位码
  171. //        else
  172. //                Display_Seg( SEG_NUM[key_num] , ~T_NUM[0]);                //数码管刷段码和位码
  173. //}
  174. u8 passward[8] = { 16,16,16,16,16,16,16,16 };
  175. u8 Seg_no = 0;
  176. void SEG_Task(void)
  177. {
  178.         u8 num = 0;
  179.         if( Seg_no ==0 )                                                                //小时十位
  180.         {
  181.                 Display_Seg( SEG_NUM[passward[0]] , ~T_NUM[0]);                //数码管刷段码和位码
  182.         }
  183.         else if( Seg_no ==1 )                                                        //小时的个位
  184.         {
  185.                 Display_Seg( SEG_NUM[passward[1]] , ~T_NUM[1]);                //数码管刷段码和位码
  186.         }        
  187.         else if( Seg_no ==2 )                                                        //第一个横杠
  188.         {
  189.                 Display_Seg( SEG_NUM[passward[2]] , ~T_NUM[2]);                //数码管刷段码和位码
  190.         }        
  191.         else if( Seg_no ==3 )                                                        //分钟的十位
  192.         {
  193.                 Display_Seg( SEG_NUM[passward[3]] , ~T_NUM[3]);                //数码管刷段码和位码
  194.         }
  195.         else if( Seg_no ==4 )
  196.         {
  197.                 Display_Seg( SEG_NUM[passward[4]] , ~T_NUM[4]);                //数码管刷段码和位码
  198.         }        
  199.         else if( Seg_no ==5 )
  200.         {
  201.                 Display_Seg( SEG_NUM[passward[5]] , ~T_NUM[5]);                //数码管刷段码和位码
  202.         }        
  203.         else if( Seg_no ==6 )
  204.         {
  205.                 Display_Seg( SEG_NUM[passward[6]] , ~T_NUM[6]);                //数码管刷段码和位码
  206.         }
  207.         else if( Seg_no ==7 )
  208.         {
  209.                 Display_Seg( SEG_NUM[passward[7]] , ~T_NUM[7]);                //数码管刷段码和位码
  210.         }        
  211.         else
  212.         {
  213.                
  214.         }
  215.         Seg_no ++;
  216.         if( Seg_no>7 )
  217.                 Seg_no=0;
  218. }
  219. u8 Key_Vol3 = 0;
  220. u8 key_no =0 ;
  221. void PW_write_Task(void)
  222. {
  223.         if( key_num <0xff )
  224.         {
  225.                 Key_Vol3 ++;
  226.                 if( Key_Vol3 == 5 )
  227.                 {
  228.                         if( key_no == 0 )
  229.                         {
  230.                                 passward[0] = 16;
  231.                                 passward[1] = 16;
  232.                                 passward[2] = 16;
  233.                                 passward[3] = 16;
  234.                                 passward[4] = 16;
  235.                                 passward[5] = 16;
  236.                                 passward[6] = 16;
  237.                                 passward[7] = 16;                        
  238.                         }                                
  239.                         passward[ key_no] = key_num ;
  240.                         key_no ++;
  241. //                        passward[7] = 17;        
  242.                         if( key_no == 8 )                //密码输入到了八位
  243.                         {
  244.                                 if((passward[0]==1) && (passward[1]==2) && (passward[2]==3) && (passward[3]==4) && (passward[4]==5) && (passward[5]==6) && (passward[6]==7) &&(passward[7]==0) )  
  245.                                 {
  246.                                         passward[0] = 17;
  247.                                         passward[1] = 17;
  248.                                         passward[2] = 17;
  249.                                         passward[3] = 17;
  250.                                         passward[4] = 17;
  251.                                         passward[5] = 17;
  252.                                         passward[6] = 17;
  253.                                         passward[7] = 1;                                       
  254.                                 }
  255.                                 else
  256.                                 {
  257.                                         passward[0] = 16;
  258.                                         passward[1] = 16;
  259.                                         passward[2] = 16;
  260.                                         passward[3] = 16;
  261.                                         passward[4] = 16;
  262.                                         passward[5] = 16;
  263.                                         passward[6] = 16;
  264.                                         passward[7] = 16;                                
  265.                                 }
  266.                                 key_no = 0;
  267.                         }
  268.                 }
  269.         }
  270.         else
  271.         {
  272.                 Key_Vol3 = 0;
  273.         }
  274. }
  275. void INT1_Init(void)
  276. {
  277.         IT1 = 1;                        //下降沿中断
  278.         EX1 = 1;                        //打开中断允许
  279.         EA = 1;                                //打开总中断
  280. }
  281. void INT_ISR(void) interrupt 2
  282. {
  283.         P01 = !P01;
  284. }
复制代码

AI8051U实验箱第13集学习手敲代码外部中断.zip

164.81 KB, 下载次数: 40

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:9
  • 最近打卡:2025-04-30 11:37:57
已绑定手机

6

主题

33

回帖

280

积分

版主

积分
280
发表于 2025-1-23 14:49:31 | 显示全部楼层
第14集IO口中断,已手敲代码,测试通过
任务1:编写IO口中断程序
截图202501231412083917.jpg

  1. #include "io.h"
  2. u8 State1 = 0;                                        //LED1初始状态
  3. u8 State2 = 0;                                        //LED2初始状态
  4. u8 State3 = 0;                                        //LED3初始状态
  5. u16 Key_Vol ;                                //按键按下持续时间
  6. u8 SEG_NUM[]=
  7. {
  8.     0x3F,       /*'0', 0*/
  9.     0x06,       /*'1', 1*/
  10.     0x5B,       /*'2', 2*/
  11.     0x4F,       /*'3', 3*/
  12.     0x66,       /*'4', 4*/
  13.     0x6D,       /*'5', 5*/
  14.     0x7D,       /*'6', 6*/
  15.     0x07,       /*'7', 7*/
  16.     0x7F,       /*'8', 8*/
  17.     0x6F,       /*'9', 9*/
  18.     0x77,       /*'A', 10*/
  19.     0x7C,       /*'B', 11*/
  20.     0x39,       /*'C', 12*/
  21.     0x5E,       /*'D', 13*/
  22.     0x79,       /*'E', 14*/
  23.     0x71,       /*'F', 15*/
  24.     0x40,       /*'-', 16*/
  25.     0x00,       /*' ', 17*/
  26.     0x80,       /*'.', 18*/
  27. };
  28. u8 T_NUM[8] =
  29. {
  30.         0X01,0X02,0X04,0X08,0X10,0X20,0X40,0X80
  31. };
  32. void LED0_Blink(void)
  33. {
  34.         State1 = !State1;
  35.         P00 = State1;
  36. }
  37. void LED1_Blink(void)
  38. {
  39.         State2 = !State2;
  40.         P01 = State2;
  41. }
  42. void LED2_Blink(void)
  43. {
  44.         State3 = !State3;
  45.         P02 = State3;
  46. }
  47. void KEY_Task(void)
  48. {
  49.         if( P33 == 0 )
  50.         {
  51.                 Key_Vol++;
  52.                 if( Key_Vol==5 )
  53.                 {
  54.                         //按键按下的任务
  55. //                        printf( "按键单击\r\n" );
  56.                         
  57.                         USB_Reset_U();
  58.                         
  59.                         IAP_CONTR = 0X20;
  60.                 }
  61.         }
  62.         else
  63.         {
  64.                 Key_Vol = 0;
  65.         }
  66.         
  67. }
  68. /*
  69.         #define ROW1        P06                        //端口定义
  70.         #define ROW2        P07
  71.         #define COL1        P00
  72.         #define COL2        P01
  73.         #define COL3        P02
  74.         #define COL4        P03
  75. */
  76. u8 key_num = 0xff;
  77. //任务1:数码管显示当前的按键号
  78. void Task_1(void)
  79. {
  80.         //①第一步:现将P0.0-P0.3输出低电平,P0.6-P0.7输出高电平,如果有按键按下,按下的那一行的IO就会变成低电平,就可以判断出哪一行按下了。
  81.         COL1 = 0;
  82.         COL2 = 0;
  83.         COL3 = 0;
  84.         COL4 = 0;
  85.         ROW1 = 1;
  86.         ROW2 = 1;
  87.         
  88.         if(( ROW1 == 0 ) || ( ROW2 == 0 ))                //如果行按键有按下
  89.         {
  90.                 if(( ROW1 ==0 ) && ( ROW2 ==0 ))        //如果两行都有按键按下,不处理
  91.                 {
  92.                         
  93.                 }
  94.                 else if((( ROW1 ==1 )&&( ROW2 ==0 )) || (( ROW1 ==0 )&&( ROW2 ==1 )))        //如果有按键按下,而且只有一颗
  95.                 {
  96.                         if( ROW1 ==0 )                                //判断哪一行,输出行开始的序号
  97.                                 key_num = 0;
  98.                         else if( ROW2 ==0 )
  99.                                 key_num = 4;
  100.                                 
  101.                         //②第二步:现将P0.0-P0.3输出高电平,P0.6-P0.7输出低电平,如果有按键按下,按下的那一列的IO就会变成低电平,就可以判断出哪一列按下了。
  102.                         COL1 = 1;
  103.                         COL2 = 1;
  104.                         COL3 = 1;
  105.                         COL4 = 1;
  106.                         ROW1 = 0;
  107.                         ROW2 = 0;
  108.                         
  109.                         if( COL1 ==0 )                                //判断哪一列,叠加按键的序号
  110.                         {
  111. //                                key_num = key_num ;
  112.                         }
  113.                         else if( COL2 ==0 )
  114.                         {
  115.                                 key_num = key_num + 1;
  116.                         }
  117.                         else if( COL3 ==0 )
  118.                         {
  119.                                 key_num = key_num + 2;
  120.                         }
  121.                         else if( COL4 ==0 )
  122.                         {
  123.                                 key_num = key_num + 3;
  124.                         }
  125.                 }
  126.                 COL1 = 0;
  127.                 COL2 = 0;
  128.                 COL3 = 0;
  129.                 COL4 = 0;
  130.                 ROW1 = 1;
  131.                 ROW2 = 1;               
  132.         }
  133.         else
  134.         {
  135.                 key_num = 0xff;
  136.         }
  137.         
  138.         //③第三步:行列组合一下就可以判断出是哪个按键按下了。
  139. }
  140. void Init_595(void)
  141. {
  142.         HC595_SER = 0;
  143.         HC595_RCK = 0;
  144.         HC595_SCK = 0;        
  145. }
  146. void Send_595( u8 dat )
  147. {
  148.         u8 i;
  149.         
  150.         for( i=0;i<8;i++ )
  151.         {
  152.                 dat <<= 1;                                //DAT = (DAT<<1);        //CY
  153.                 HC595_SER = CY;                //先把数据写到引脚上
  154.                 HC595_SCK = 1;                        //输出上升沿的时钟信号
  155.                 HC595_SCK = 0;
  156.         }
  157. }
  158. void Display_Seg(u8 HC595_1,u8 HC595_2)
  159. {
  160.         Send_595(HC595_1);                        //数码管段码输出  高电平点亮
  161.         Send_595(HC595_2);                        //数码管位码      低电平点亮
  162.         
  163.         HC595_RCK = 1;                                //数据输出        
  164.         HC595_RCK = 0;
  165. }
  166. //void SEG_Task(void)
  167. //{
  168. //        if( key_num == 255 )
  169. //                Display_Seg( SEG_NUM[17] , ~T_NUM[0]);                //数码管刷段码和位码
  170. //        else
  171. //                Display_Seg( SEG_NUM[key_num] , ~T_NUM[0]);                //数码管刷段码和位码
  172. //}
  173. u8 passward[8] = { 16,16,16,16,16,16,16,16 };
  174. u8 Seg_no = 0;
  175. void SEG_Task(void)
  176. {
  177.         u8 num = 0;
  178.         if( Seg_no ==0 )                                                                //小时十位
  179.         {
  180.                 Display_Seg( SEG_NUM[passward[0]] , ~T_NUM[0]);                //数码管刷段码和位码
  181.         }
  182.         else if( Seg_no ==1 )                                                        //小时的个位
  183.         {
  184.                 Display_Seg( SEG_NUM[passward[1]] , ~T_NUM[1]);                //数码管刷段码和位码
  185.         }        
  186.         else if( Seg_no ==2 )                                                        //第一个横杠
  187.         {
  188.                 Display_Seg( SEG_NUM[passward[2]] , ~T_NUM[2]);                //数码管刷段码和位码
  189.         }        
  190.         else if( Seg_no ==3 )                                                        //分钟的十位
  191.         {
  192.                 Display_Seg( SEG_NUM[passward[3]] , ~T_NUM[3]);                //数码管刷段码和位码
  193.         }
  194.         else if( Seg_no ==4 )
  195.         {
  196.                 Display_Seg( SEG_NUM[passward[4]] , ~T_NUM[4]);                //数码管刷段码和位码
  197.         }        
  198.         else if( Seg_no ==5 )
  199.         {
  200.                 Display_Seg( SEG_NUM[passward[5]] , ~T_NUM[5]);                //数码管刷段码和位码
  201.         }        
  202.         else if( Seg_no ==6 )
  203.         {
  204.                 Display_Seg( SEG_NUM[passward[6]] , ~T_NUM[6]);                //数码管刷段码和位码
  205.         }
  206.         else if( Seg_no ==7 )
  207.         {
  208.                 Display_Seg( SEG_NUM[passward[7]] , ~T_NUM[7]);                //数码管刷段码和位码
  209.         }        
  210.         else
  211.         {
  212.                
  213.         }
  214.         Seg_no ++;
  215.         if( Seg_no>7 )
  216.                 Seg_no=0;
  217. }
  218. u8 Key_Vol3 = 0;
  219. u8 key_no =0 ;
  220. void PW_write_Task(void)
  221. {
  222.         if( key_num <0xff )
  223.         {
  224.                 Key_Vol3 ++;
  225.                 if( Key_Vol3 == 5 )
  226.                 {
  227.                         if( key_no == 0 )
  228.                         {
  229.                                 passward[0] = 16;
  230.                                 passward[1] = 16;
  231.                                 passward[2] = 16;
  232.                                 passward[3] = 16;
  233.                                 passward[4] = 16;
  234.                                 passward[5] = 16;
  235.                                 passward[6] = 16;
  236.                                 passward[7] = 16;                        
  237.                         }                                
  238.                         passward[ key_no] = key_num ;
  239.                         key_no ++;
  240. //                        passward[7] = 17;        
  241.                         if( key_no == 8 )                //密码输入到了八位
  242.                         {
  243.                                 if((passward[0]==1) && (passward[1]==2) && (passward[2]==3) && (passward[3]==4) && (passward[4]==5) && (passward[5]==6) && (passward[6]==7) &&(passward[7]==0) )  
  244.                                 {
  245.                                         passward[0] = 17;
  246.                                         passward[1] = 17;
  247.                                         passward[2] = 17;
  248.                                         passward[3] = 17;
  249.                                         passward[4] = 17;
  250.                                         passward[5] = 17;
  251.                                         passward[6] = 17;
  252.                                         passward[7] = 1;                                       
  253.                                 }
  254.                                 else
  255.                                 {
  256.                                         passward[0] = 16;
  257.                                         passward[1] = 16;
  258.                                         passward[2] = 16;
  259.                                         passward[3] = 16;
  260.                                         passward[4] = 16;
  261.                                         passward[5] = 16;
  262.                                         passward[6] = 16;
  263.                                         passward[7] = 16;                                
  264.                                 }
  265.                                 key_no = 0;
  266.                         }
  267.                 }
  268.         }
  269.         else
  270.         {
  271.                 Key_Vol3 = 0;
  272.         }
  273. }
  274. //void INT1_Init(void)
  275. //{
  276. //   IT1=1;   //下降沿中断
  277. //         EX1=1;   //打开中断允许
  278. //         EA=1;    // 打开总中断
  279. //}
  280. //void INT_ISR(void)interrupt 2
  281. //{
  282. //                P01=!P01;
  283. //}
  284. void P3_IO_Init(void)
  285. {
  286.                 P3IM0=0X00;  //IO中断模式设置为下降沿
  287.                 P3IM1=0X00;
  288.         
  289.                 P3INTE=0X08;  //打开中断
  290. }
  291. void P3_IO_ISR(void)    interrupt 40
  292. {
  293.                 u8 intf;
  294.         
  295.                 intf=P3INTF;
  296.                
  297.                 if(intf)  //判断有没有io触发中断
  298.                 {
  299.                         P3INTF=0;
  300.                         
  301.                         if (intf & 0x08)  //判断是否是P33按键按下
  302.                         {
  303.                                         P01=!P01;
  304.                         }
  305.                 }
  306. }
复制代码
任务2:编写P4端口的I0中断 打断 P3低电平中断的的程序
1、设置P33优先级比P47高  按下P33显示1,按下P47显示2,
P33高优先级可以打断P47低优先级中断

截图202501231428468506.jpg


  1. #include "io.h"
  2. u8 State1 = 0;                                        //LED1初始状态
  3. u8 State2 = 0;                                        //LED2初始状态
  4. u8 State3 = 0;                                        //LED3初始状态
  5. u16 Key_Vol ;                                //按键按下持续时间
  6. u8 SEG_NUM[]=
  7. {
  8.     0x3F,       /*'0', 0*/
  9.     0x06,       /*'1', 1*/
  10.     0x5B,       /*'2', 2*/
  11.     0x4F,       /*'3', 3*/
  12.     0x66,       /*'4', 4*/
  13.     0x6D,       /*'5', 5*/
  14.     0x7D,       /*'6', 6*/
  15.     0x07,       /*'7', 7*/
  16.     0x7F,       /*'8', 8*/
  17.     0x6F,       /*'9', 9*/
  18.     0x77,       /*'A', 10*/
  19.     0x7C,       /*'B', 11*/
  20.     0x39,       /*'C', 12*/
  21.     0x5E,       /*'D', 13*/
  22.     0x79,       /*'E', 14*/
  23.     0x71,       /*'F', 15*/
  24.     0x40,       /*'-', 16*/
  25.     0x00,       /*' ', 17*/
  26.     0x80,       /*'.', 18*/
  27. };
  28. u8 T_NUM[8] =
  29. {
  30.         0X01,0X02,0X04,0X08,0X10,0X20,0X40,0X80
  31. };
  32. void LED0_Blink(void)
  33. {
  34.         State1 = !State1;
  35.         P00 = State1;
  36. }
  37. void LED1_Blink(void)
  38. {
  39.         State2 = !State2;
  40.         P01 = State2;
  41. }
  42. void LED2_Blink(void)
  43. {
  44.         State3 = !State3;
  45.         P02 = State3;
  46. }
  47. void KEY_Task(void)
  48. {
  49.         if( P33 == 0 )
  50.         {
  51.                 Key_Vol++;
  52.                 if( Key_Vol==5 )
  53.                 {
  54.                         //按键按下的任务
  55. //                        printf( "按键单击\r\n" );
  56.                         
  57.                         USB_Reset_U();
  58.                         
  59.                         IAP_CONTR = 0X20;
  60.                 }
  61.         }
  62.         else
  63.         {
  64.                 Key_Vol = 0;
  65.         }
  66.         
  67. }
  68. /*
  69.         #define ROW1        P06                        //端口定义
  70.         #define ROW2        P07
  71.         #define COL1        P00
  72.         #define COL2        P01
  73.         #define COL3        P02
  74.         #define COL4        P03
  75. */
  76. u8 key_num = 0xff;
  77. //任务1:数码管显示当前的按键号
  78. void Task_1(void)
  79. {
  80.         //①第一步:现将P0.0-P0.3输出低电平,P0.6-P0.7输出高电平,如果有按键按下,按下的那一行的IO就会变成低电平,就可以判断出哪一行按下了。
  81.         COL1 = 0;
  82.         COL2 = 0;
  83.         COL3 = 0;
  84.         COL4 = 0;
  85.         ROW1 = 1;
  86.         ROW2 = 1;
  87.         
  88.         if(( ROW1 == 0 ) || ( ROW2 == 0 ))                //如果行按键有按下
  89.         {
  90.                 if(( ROW1 ==0 ) && ( ROW2 ==0 ))        //如果两行都有按键按下,不处理
  91.                 {
  92.                         
  93.                 }
  94.                 else if((( ROW1 ==1 )&&( ROW2 ==0 )) || (( ROW1 ==0 )&&( ROW2 ==1 )))        //如果有按键按下,而且只有一颗
  95.                 {
  96.                         if( ROW1 ==0 )                                //判断哪一行,输出行开始的序号
  97.                                 key_num = 0;
  98.                         else if( ROW2 ==0 )
  99.                                 key_num = 4;
  100.                                 
  101.                         //②第二步:现将P0.0-P0.3输出高电平,P0.6-P0.7输出低电平,如果有按键按下,按下的那一列的IO就会变成低电平,就可以判断出哪一列按下了。
  102.                         COL1 = 1;
  103.                         COL2 = 1;
  104.                         COL3 = 1;
  105.                         COL4 = 1;
  106.                         ROW1 = 0;
  107.                         ROW2 = 0;
  108.                         
  109.                         if( COL1 ==0 )                                //判断哪一列,叠加按键的序号
  110.                         {
  111. //                                key_num = key_num ;
  112.                         }
  113.                         else if( COL2 ==0 )
  114.                         {
  115.                                 key_num = key_num + 1;
  116.                         }
  117.                         else if( COL3 ==0 )
  118.                         {
  119.                                 key_num = key_num + 2;
  120.                         }
  121.                         else if( COL4 ==0 )
  122.                         {
  123.                                 key_num = key_num + 3;
  124.                         }
  125.                 }
  126.                 COL1 = 0;
  127.                 COL2 = 0;
  128.                 COL3 = 0;
  129.                 COL4 = 0;
  130.                 ROW1 = 1;
  131.                 ROW2 = 1;               
  132.         }
  133.         else
  134.         {
  135.                 key_num = 0xff;
  136.         }
  137.         
  138.         //③第三步:行列组合一下就可以判断出是哪个按键按下了。
  139. }
  140. void Init_595(void)
  141. {
  142.         HC595_SER = 0;
  143.         HC595_RCK = 0;
  144.         HC595_SCK = 0;        
  145. }
  146.         
  147. void Send_595( u8 dat )
  148. {
  149.         u8 i;
  150.         
  151.         for( i=0;i<8;i++ )
  152.         {
  153.                 dat <<= 1;                                //DAT = (DAT<<1);        //CY
  154.                 HC595_SER = CY;                //先把数据写到引脚上
  155.                 HC595_SCK = 1;                        //输出上升沿的时钟信号
  156.                 HC595_SCK = 0;
  157.         }
  158. }
  159. void Display_Seg(u8 HC595_1,u8 HC595_2)
  160. {
  161.         Send_595(HC595_1);                        //数码管段码输出  高电平点亮
  162.         Send_595(HC595_2);                        //数码管位码      低电平点亮
  163.         
  164.         HC595_RCK = 1;                                //数据输出        
  165.         HC595_RCK = 0;
  166. }
  167. //void SEG_Task(void)
  168. //{
  169. //        if( key_num == 255 )
  170. //                Display_Seg( SEG_NUM[17] , ~T_NUM[0]);                //数码管刷段码和位码
  171. //        else
  172. //                Display_Seg( SEG_NUM[key_num] , ~T_NUM[0]);                //数码管刷段码和位码
  173. //}
  174. u8 passward[8] = { 17,17,17,17,17,17,17,17 };
  175. u8 Seg_no = 0;
  176. void SEG_Task(void)
  177. {
  178.         u8 num = 0;
  179.         if( Seg_no ==0 )                                                                //小时十位
  180.         {
  181.                 Display_Seg( SEG_NUM[passward[0]] , ~T_NUM[0]);                //数码管刷段码和位码
  182.         }
  183.         else if( Seg_no ==1 )                                                        //小时的个位
  184.         {
  185.                 Display_Seg( SEG_NUM[passward[1]] , ~T_NUM[1]);                //数码管刷段码和位码
  186.         }        
  187.         else if( Seg_no ==2 )                                                        //第一个横杠
  188.         {
  189.                 Display_Seg( SEG_NUM[passward[2]] , ~T_NUM[2]);                //数码管刷段码和位码
  190.         }        
  191.         else if( Seg_no ==3 )                                                        //分钟的十位
  192.         {
  193.                 Display_Seg( SEG_NUM[passward[3]] , ~T_NUM[3]);                //数码管刷段码和位码
  194.         }
  195.         else if( Seg_no ==4 )
  196.         {
  197.                 Display_Seg( SEG_NUM[passward[4]] , ~T_NUM[4]);                //数码管刷段码和位码
  198.         }        
  199.         else if( Seg_no ==5 )
  200.         {
  201.                 Display_Seg( SEG_NUM[passward[5]] , ~T_NUM[5]);                //数码管刷段码和位码
  202.         }        
  203.         else if( Seg_no ==6 )
  204.         {
  205.                 Display_Seg( SEG_NUM[passward[6]] , ~T_NUM[6]);                //数码管刷段码和位码
  206.         }
  207.         else if( Seg_no ==7 )
  208.         {
  209.                 Display_Seg( SEG_NUM[passward[7]] , ~T_NUM[7]);                //数码管刷段码和位码
  210.         }        
  211.         else
  212.         {
  213.                
  214.         }
  215.         Seg_no ++;
  216.         if( Seg_no>7 )
  217.                 Seg_no=0;
  218. }
  219. u8 Key_Vol3 = 0;
  220. u8 key_no =0 ;
  221. void PW_write_Task(void)
  222. {
  223.         if( key_num <0xff )
  224.         {
  225.                 Key_Vol3 ++;
  226.                 if( Key_Vol3 == 5 )
  227.                 {
  228.                         if( key_no == 0 )
  229.                         {
  230.                                 passward[0] = 16;
  231.                                 passward[1] = 16;
  232.                                 passward[2] = 16;
  233.                                 passward[3] = 16;
  234.                                 passward[4] = 16;
  235.                                 passward[5] = 16;
  236.                                 passward[6] = 16;
  237.                                 passward[7] = 16;                        
  238.                         }                                
  239.                         passward[ key_no] = key_num ;
  240.                         key_no ++;
  241. //                        passward[7] = 17;        
  242.                         if( key_no == 8 )                //密码输入到了八位
  243.                         {
  244.                                 if((passward[0]==1) && (passward[1]==2) && (passward[2]==3) && (passward[3]==4) && (passward[4]==5) && (passward[5]==6) && (passward[6]==7) &&(passward[7]==0) )  
  245.                                 {
  246.                                         passward[0] = 17;
  247.                                         passward[1] = 17;
  248.                                         passward[2] = 17;
  249.                                         passward[3] = 17;
  250.                                         passward[4] = 17;
  251.                                         passward[5] = 17;
  252.                                         passward[6] = 17;
  253.                                         passward[7] = 1;                                       
  254.                                 }
  255.                                 else
  256.                                 {
  257.                                         passward[0] = 16;
  258.                                         passward[1] = 16;
  259.                                         passward[2] = 16;
  260.                                         passward[3] = 16;
  261.                                         passward[4] = 16;
  262.                                         passward[5] = 16;
  263.                                         passward[6] = 16;
  264.                                         passward[7] = 16;                                
  265.                                 }
  266.                                 key_no = 0;
  267.                         }
  268.                 }
  269.         }
  270.         else
  271.         {
  272.                 Key_Vol3 = 0;
  273.         }
  274. }
  275. //void INT1_Init(void)
  276. //{
  277. //   IT1=1;   //下降沿中断
  278. //         EX1=1;   //打开中断允许
  279. //         EA=1;    // 打开总中断
  280. //}
  281. //void INT_ISR(void)interrupt 2
  282. //{
  283. //                P01=!P01;
  284. //}
  285. void P3_IO_Init(void)
  286. {
  287.                 P3IM0=0X00;  //IO中断模式设置为下降沿
  288.                 P3IM1=0Xff;
  289.         
  290.                 P3INTE=0X08;  //打开中断
  291. }
  292. void P3_IO_ISR(void)    interrupt 40
  293. {
  294.                 u8 intf;
  295.         
  296.                 intf=P3INTF;
  297.                
  298.                 if(intf)  //判断有没有io触发中断
  299.                 {
  300.                         P3INTF=0;
  301.                         
  302.                         if (intf & 0x08)  //判断是否是P33按键按下
  303.                         {
  304.                                 passward[0] = 1;
  305.                                         //P01=!P01;
  306.                         }
  307.                 }
  308. }        
  309. void P4_IO_Init(void)
  310. {
  311.                 P4IM0=0X00;  //IO中断模式设置为下降沿
  312.                 P4IM1=0Xff;
  313.         
  314.                 P4INTE=0X80;  //打开中断
  315.         
  316.         PINIPH  |= (1<<4);   //写入最高优先级
  317.         PINIPL  |= (1<<4);
  318. }
  319. void P4_IO_ISR(void)    interrupt 41
  320. {
  321.                 u8 intf;
  322.         
  323.                 intf=P4INTF;
  324.                
  325.                 if(intf)  //判断有没有io触发中断
  326.                 {
  327.                         P4INTF=0;
  328.                         
  329.                         if (intf & 0x80)  //判断是否是P33按键按下
  330.                         {
  331.                                         passward[0] = 2;
  332.                         }
  333.                 }
  334. }        
复制代码
2、设置P47优先级比P33高  按下P33显示1,按下P47显示2,P47高优先级可以打断P33低优先级中断

截图202501231444213217.jpg


AI8051U实验箱第14集学习手敲代码IO中断.zip

166.43 KB, 下载次数: 28

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:9
  • 最近打卡:2025-04-30 11:37:57
已绑定手机

6

主题

33

回帖

280

积分

版主

积分
280
发表于 2025-1-24 11:50:37 | 显示全部楼层
第15集 定时器做计数器,已手敲代码,测试通过

任务1:编写定时器1计数的程序  为了方便计数,10个脉冲中断一次

1

1


  1. #include "tim.h"
  2. u32 Count_T1 = 0;
  3. void TIM1_Count_Init(void)
  4. {
  5.         T1_CT = 1;       //设置为外部计数
  6.         T1_M1 = 0;       //设置为16位自动重载
  7.         T1_M0 = 0;
  8.         T1_GATE = 0;
  9.         
  10.         TH1 = (65536-Count_num)>>8;     //65526
  11.         TL1 = (65536-Count_num);
  12.         
  13.         P3PU |= 0x20;
  14.         TR1 = 1;      //启动定时器1
  15.         ET1 = 1;      //打开定时器1外部中断
  16.         
  17. }
  18. void Timer1_Isr(void) interrupt 3                //1MS执行一次
  19. {
  20.     Count_T1 ++;     //T1引脚检测到十个脉冲就会溢出一次
  21. }
  22. void T1_RunTask(void)
  23. {
  24.         u32 count_th_tl = 0;
  25.         count_th_tl = ((u16)TH1 <<8) + (u16)TL1;
  26.         count_th_tl -= 65526;
  27.         
  28.         SEG7_ShowLong(Count_T1*Count_num+count_th_tl,10);
  29. }
复制代码
任务2 :编写INT1测量低电平时间(由按键模拟信号,100us的计数周期计数)
截图202501241324488014.jpg

  1. #include "tim.h"
  2. u32 Count_T1 = 0;
  3. //void TIM1_Count_Init(void)
  4. //{
  5. //        T1_CT = 1;                        //设置为外部计数
  6. //        T1_M1 = 0;                        //设置为16位自动重载
  7. //        T1_M0 = 0;
  8. //        T1_GATE = 0;
  9. //        
  10. //        TH1 = (65536-Count_num)>>8;        //65526
  11. //        TL1 = (65536-Count_num);
  12. //        
  13. //        P3PU |= 0x20;
  14. //        TR1 = 1;                        //启动定时器1
  15. //        ET1 = 1;                        //打开定时器1外部中断
  16. //        
  17. //}
  18. //void Timer1_Isr(void) interrupt 3                //1MS执行一次
  19. //{
  20. //        Count_T1 ++;                        //T1引脚检测到十个脉冲就会溢出一次
  21. //}
  22. //void T1_RunTask(void)
  23. //{
  24. //        u32 count_th_tl = 0;
  25. //        count_th_tl = ((u16)TH1 << 8) + (u16)TL1;
  26. //        count_th_tl -= 65526;
  27. //        
  28. //        SEG7_ShowLong(Count_T1*Count_num+count_th_tl,10);
  29. //}
  30. void Timer1_Isr(void) interrupt 3
  31. {
  32.                 static u32 count_p33 = 0;
  33.         
  34.         if( P33 == 0 )                //按键按下开始计数
  35.         {
  36.                 count_p33 ++ ;
  37.         }
  38.         else
  39.         {
  40.                 if( count_p33>0 )                //表示之前按下了这个按键
  41.                 {
  42.                         Count_T1 = count_p33;
  43.                 }
  44.                 count_p33 =0;
  45.         }
  46. }
  47. void Timer1_Init(void)                //100微秒@24.000MHz
  48. {
  49.         AUXR &= 0xBF;                        //定时器时钟12T模式
  50.         TMOD &= 0x0F;                        //设置定时器模式
  51.         TL1 = 0x38;                                //设置定时初始值
  52.         TH1 = 0xFF;                                //设置定时初始值
  53.         TF1 = 0;                                //清除TF1标志
  54.         TR1 = 1;                                //定时器1开始计时
  55.         ET1 = 1;                                //使能定时器1中断
  56. }
  57. void T1_RunTask(void)
  58. {
  59.         //SEG7_ShowLong(Count_T1,10);        //显示整数
  60.         SEG7_ShowString("%07.01f",((float)Count_T1)/10);
  61. }
复制代码



AI8051U实验箱第15集学习手敲代码定时器做count.zip

411.26 KB, 下载次数: 36

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:9
  • 最近打卡:2025-04-30 11:37:57
已绑定手机

6

主题

33

回帖

280

积分

版主

积分
280
发表于 2025-2-5 16:09:27 | 显示全部楼层
第16集DS18B20测温,已手敲代码,测试通过。
数码管显示室温,捏住测温传感器,温度逐渐上升。

截图202502051607135604.jpg


  1. #include "18b20.h"
  2. u8  MinusFlag = 0;                //如果等于0 ,正数;等于1,负数
  3. u32 Temp_18b20;                //最终的温度,0.0625
  4. void Delay480us(void)        //@24.000MHz
  5. {
  6.         unsigned long edata i;
  7.         _nop_();
  8.         _nop_();
  9.         _nop_();
  10.         i = 2878UL;
  11.         while (i) i--;
  12. }
  13. void Delay60us(void)        //@24.000MHz
  14. {
  15.         unsigned long edata i;
  16.         _nop_();
  17.         _nop_();
  18.         _nop_();
  19.         i = 358UL;
  20.         while (i) i--;
  21. }
  22. void Delay1us(void)        //@24.000MHz
  23. {
  24.         unsigned long edata i;
  25.         _nop_();
  26.         _nop_();
  27.         _nop_();
  28.         i = 4UL;
  29.         while (i) i--;
  30. }
  31. //复位(输出0保持480us,输出1保持60us,读取当前电平,延时420us)
  32. void DS18B20_Reset(void)
  33. {
  34.         u8 flag = 1;
  35.         
  36.         while( flag )                //只要括号里的变量大于0,就会一直执行
  37.         {
  38.                 DQ = 0;
  39.                 Delay480us();
  40.                 DQ = 1;
  41.                 Delay60us();
  42.                 flag = DQ;                        //设备存在,会拉低总线
  43.                 Delay480us();
  44.         }
  45. }
  46.         
  47. //写逻辑0(输出0保持60us+,输出1保持1us+)
  48. void DS18B20_Write_0(void)
  49. {
  50.         DQ = 0;
  51.         Delay60us();
  52.         DQ = 1;
  53.         Delay1us();
  54.         Delay1us();
  55. }
  56. //写逻辑1(输出0保持1us+,输出1保持60us+)
  57. void DS18B20_Write_1(void)
  58. {
  59.         DQ = 0;
  60.         Delay1us();
  61.         Delay1us();
  62.         DQ = 1;
  63.         Delay60us();
  64. }
  65. //读逻辑0/1(输出0保持1us+,输出1保持1us+,读取当前电平,延时60us)
  66. bit DS18B20_Read(void)
  67. {
  68.         bit state = 0;
  69.         
  70.         DQ = 0;
  71.         Delay1us();
  72.         Delay1us();        
  73.         DQ = 1;
  74.         Delay1us();
  75.         Delay1us();        
  76.         state = DQ;                //暂时保存这个DQ的数值
  77.         Delay60us();
  78.         
  79.         return state;
  80. }
  81. //写1字节(先输出低位,在输出高位)
  82. void DS18B20_WriteByte( u8 dat )
  83. {
  84.         u8 i;
  85.         for(i=0;i<8;i++)
  86.         {
  87.                 if( dat & 0x01 )        //最低位是1.发逻辑1电平
  88.                 {
  89.                         DS18B20_Write_1();
  90.                 }
  91.                 else                                //否则.发逻辑0电平
  92.                 {
  93.                         DS18B20_Write_0();
  94.                 }
  95.                 dat >>= 1;                        //dat = (dat>>1);
  96.         }
  97. }
  98. //读1字节(先读到的是低位,后读到的是高位)
  99. u8 DS18B20_ReadByte(void )
  100. {
  101.         u8 i;
  102.         u8 dat=0;                                //数据暂存,
  103.         
  104.         for(i=0;i<8;i++)                //循环读取八次
  105.         {
  106.                 dat >>= 1;
  107.                 if( DS18B20_Read() )        //如果读回来的是逻辑1   //0000 0000  ->1000 0000 -> 0100 0000
  108.                 {
  109.                         dat |= 0x80;
  110.                 }
  111.                 else
  112.                 {
  113.                 }
  114.         }
  115.         return dat;
  116. }
  117. //复位-CCH-44H-等待-复位-CCH-BEH-读取2字节温度数据-换算)
  118. void DS18B20_ReadTemp(void)
  119. {
  120.         u8 TempH = 0;
  121.         u8 TempL = 0;
  122.         u16 Temp = 0;
  123. //---------------------发送检测命令---------------------        
  124.         DS18B20_Reset();                        //1.发送复位命令
  125.         DS18B20_WriteByte(0xcc);        //2.跳过ROM命令
  126.         DS18B20_WriteByte(0x44);        //3.开始转化命令
  127.         while( !DQ );                                //4.等待这个引脚变成高电平
  128.         
  129. //---------------------发送读取命令---------------------        
  130.         DS18B20_Reset();                        //1.发送复位命令
  131.         DS18B20_WriteByte(0xcc);        //2.跳过ROM命令
  132.         DS18B20_WriteByte(0xBE);        //3.开始转化命令        
  133.         TempL = DS18B20_ReadByte(); //读取低字节温度
  134.         TempH = DS18B20_ReadByte(); //读取高字节温度        
  135.         
  136.         if( TempH & 0x80 )                        //如果最高位是1,这个就是负数
  137.         {
  138.                 MinusFlag = 1;
  139.                 Temp = (((u16)TempH << 8) | ((u16)TempL << 0));
  140.                 Temp = (~Temp) +1;
  141.                 Temp_18b20 = (u32)Temp*625;
  142.         }
  143.         else
  144.         {
  145.                 MinusFlag = 0;
  146.                 Temp = (((u16)TempH << 8) | ((u16)TempL << 0));
  147.                 Temp_18b20 = (u32)Temp*625;
  148.         }
  149. }
复制代码


AI8051U实验箱第16集学习手敲代码DS18B20测温.zip

220.62 KB, 下载次数: 23

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:9
  • 最近打卡:2025-04-30 11:37:57
已绑定手机

6

主题

33

回帖

280

积分

版主

积分
280
发表于 2025-2-14 10:13:36 | 显示全部楼层
第17集串口的简单应用,已手敲代码,测试通过。

截图202502141008585970.jpg


  1. #include "usart.h"
  2. #include "io.h"
  3. u8 Rec_Dat[50];  //接收缓冲区
  4. u8 Rec_Num=0;    //接收计数
  5. bit B_TX2_Busy=0;
  6. void Uart2_Isr(void) interrupt 8
  7. {
  8.         if (S2CON & 0x02)        //检测串口2发送中断
  9.         {
  10.                 S2CON &= ~0x02;        //清除串口2发送中断请求位
  11.                 B_TX2_Busy=0;
  12.         }
  13.         if (S2CON & 0x01)        //检测串口2接收中断
  14.         {
  15.                 S2CON &= ~0x01;        //清除串口2接收中断请求位
  16.                 Rec_Dat[Rec_Num++]=S2BUF;
  17.         }
  18. }
  19. void Uart2_Init(void)        //9600bps@24.000MHz
  20. {
  21.         P_SW2 |= 0x01;                                                //UART2/USART2: RxD2(P4.6), TxD2(P4.7)
  22.         S2CON = 0x50;                //8位数据,可变波特率
  23.         AUXR |= 0x04;                //定时器时钟1T模式
  24.         T2L = 0x8F;                        //设置定时初始值
  25.         T2H = 0xFD;                        //设置定时初始值
  26.         AUXR |= 0x10;                //定时器2开始计时
  27.         IE2 |= 0x01;                //使能串口2中断
  28.         
  29.         Rec_Num=0;
  30.         B_TX2_Busy=0;
  31. }
  32. void Uart2_SendStr(u8 *puts)   //串口数据发送函数
  33. {
  34.         for(; *puts !=0;  puts++)     //遇到停止符0结束
  35.         {
  36.                 S2BUF = *puts;
  37.                 B_TX2_Busy=1;
  38.                 while(B_TX2_Busy);
  39.         }
  40. }
  41. //1.发送OPEN\r\n打开数码管,数码管显示“----”
  42. //2.发送CLOSE\r\n打开数码管,数码管全部熄灭
  43. void Usart2_RunTask(void)
  44. {
  45.          if(Rec_Num>=6)     //是否接收到了6位以上的数据
  46.          {
  47.                  if ((Rec_Dat[Rec_Num-1]=='\n') && (Rec_Dat[Rec_Num-2]=='\r'))  //末尾判断
  48.                  {
  49.                           if((Rec_Dat[Rec_Num-6]=='O') && (Rec_Dat[Rec_Num-5]=='P') && (Rec_Dat[Rec_Num-4]=='E') && (Rec_Dat[Rec_Num-3]=='N'))
  50.                           {
  51.                                   passward[0]=16;
  52.                   passward[1]=16;
  53.                   passward[2]=16;
  54.                   passward[3]=16;
  55.                                   Uart2_SendStr("打开成功!\r\n");
  56.                           }
  57.                           else if((Rec_Dat[Rec_Num-7]=='C') && (Rec_Dat[Rec_Num-6]=='L') && (Rec_Dat[Rec_Num-5]=='O') && (Rec_Dat[Rec_Num-4]=='S')&& (Rec_Dat[Rec_Num-3]=='E'))
  58.               {
  59.                   passward[0]=17;
  60.                   passward[1]=17;
  61.                   passward[2]=17;
  62.                   passward[3]=17;
  63.                                   Uart2_SendStr("关闭成功!\r\n");
  64.                       }
  65.                            Rec_Num=0;
  66.              }
  67.      }
  68. }
复制代码


AI8051U实验箱第17集学习手敲代码串口的简单应用.zip

215.29 KB, 下载次数: 12

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:9
  • 最近打卡:2025-04-30 11:37:57
已绑定手机

6

主题

33

回帖

280

积分

版主

积分
280
发表于 2025-3-11 13:35:11 | 显示全部楼层
第18集 串口的高级应用,已手敲代码,测试通过
任务1:使用奇校验,8位数据位,1位停止位的数据,发送"OPEN\r\n"
#include "usart.h"
#include "io.h"

u8 Rec_Dat[50];  //接收缓冲区
u8 Rec_Num=0;    //接收计数
bit B_TX2_Busy=0;

void Uart2_Isr(void) interrupt 8
{
        u8 dat;
        if (S2CON & 0x02)        //检测串口2发送中断
        {
                S2CON &= ~0x02;        //清除串口2发送中断请求位
                B_TX2_Busy=0;
        }
        if (S2CON & 0x01)        //检测串口2接收中断
        {
                S2CON &= ~0x01;        //清除串口2接收中断请求位
                dat = S2BUF;
                ACC = dat;
                if(S2RB8 == (!P))  //奇校验
                Rec_Dat[Rec_Num++]=dat;
        }
}

void Uart2_Init(void)        //9600bps@24.000MHz
{
        P_SW2 |= 0x01;                                                //UART2/USART2: RxD2(P4.6), TxD2(P4.7)

    S2CON = 0xD0;                //9位数据,可变波特率
        AUXR |= 0x04;                //定时器时钟1T模式
        T2L = 0x8F;                        //设置定时初始值
        T2H = 0xFD;                        //设置定时初始值
        AUXR |= 0x10;                //定时器2开始计时
        IE2 |= 0x01;                //使能串口2中断
        
        Rec_Num=0;
        B_TX2_Busy=0;
}

void Uart2_SendStr(u8 *puts)   //串口数据发送函数
{
            u8 dat;
        for(; *puts !=0;  puts++)     //遇到停止符0结束
        {
                            dat = *puts;
                            ACC = dat;
                        if(P)
                                S2TB8 = 0;
                        else
                                S2TB8 = 1;
                S2BUF = dat;
                B_TX2_Busy=1;
                while(B_TX2_Busy);
        }
}

//1.发送OPEN\r\n打开数码管,数码管显示“----”
//2.发送CLOSE\r\n打开数码管,数码管全部熄灭

void Usart2_RunTask(void)
{
         if(Rec_Num>=6)     //是否接收到了6位以上的数据
         {
                 if ((Rec_Dat[Rec_Num-1]=='\n') && (Rec_Dat[Rec_Num-2]=='\r'))  //末尾判断
                 {
                          if((Rec_Dat[Rec_Num-6]=='O') && (Rec_Dat[Rec_Num-5]=='P') && (Rec_Dat[Rec_Num-4]=='E') && (Rec_Dat[Rec_Num-3]=='N'))
                          {
                                  passward[0]=16;
                  passward[1]=16;
                  passward[2]=16;
                  passward[3]=16;
                                  Uart2_SendStr("打开成功!\r\n");
                          }
                          else if((Rec_Dat[Rec_Num-7]=='C') && (Rec_Dat[Rec_Num-6]=='L') && (Rec_Dat[Rec_Num-5]=='O') && (Rec_Dat[Rec_Num-4]=='S')&& (Rec_Dat[Rec_Num-3]=='E'))
              {
                  passward[0]=17;
                  passward[1]=17;
                  passward[2]=17;
                  passward[3]=17;
                                  Uart2_SendStr("关闭成功!\r\n");
                      }
                           Rec_Num=0;
             }
     }
}
   
任务2:串口超时中断
  1. #include "usart.h"
  2. #include "io.h"
  3. u8 Rec_Dat[50];  //接收缓冲区
  4. u8 Rec_Num=0;    //接收计数
  5. bit B_TX2_Busy=0;
  6. u8 B_RX2_OK = 0;        //串口接收完成标志位
  7. void Uart2_Isr(void) interrupt 8
  8. {
  9.         if (S2CON & 0x02)        //检测串口2发送中断
  10.         {
  11.                 S2CON &= ~0x02;        //清除串口2发送中断请求位
  12.                 B_TX2_Busy=0;
  13.         }
  14.         if (S2CON & 0x01)        //检测串口2接收中断
  15.         {
  16.                 S2CON &= ~0x01;        //清除串口2接收中断请求位
  17.                
  18.                 UR2TOCR = 0xe0;                             //开启超时中断,使用系统时钟
  19.                
  20.                 Rec_Dat[Rec_Num++]=S2BUF;
  21.         }
  22.         
  23.          if(UR2TOSR & 0x01)                              //串口超时中断
  24.     {
  25.         B_RX2_OK = 1;                               //接收完成标志位
  26.         UR2TOSR = 0x00;                             //清除超时标志位
  27.         UR2TOCR = 0x00;                             //关闭超时中断
  28.     }
  29. }
  30. void Uart2_Init(void)        //9600bps@24.000MHz
  31. {
  32.         P_SW2 |= 0x01;                                                //UART2/USART2: RxD2(P4.6), TxD2(P4.7)
  33.         S2CON = 0x50;                //8位数据,可变波特率
  34.         AUXR |= 0x04;                //定时器时钟1T模式
  35.         T2L = 0x8F;                        //设置定时初始值
  36.         T2H = 0xFD;                        //设置定时初始值
  37.         AUXR |= 0x10;                //定时器2开始计时
  38.         IE2 |= 0x01;                //使能串口2中断
  39.         
  40.         UR2TOCR = 0x00;          //关闭超时中断                              
  41.     UR2TOTL = 0x04;                                 
  42.     UR2TOTH = 0x3b;                              
  43.     UR2TOTE = 0x01;
  44.         
  45.         Rec_Num=0;
  46.         B_TX2_Busy=0;
  47.         B_RX2_OK = 0;
  48. }
  49. void Uart2_SendStr(u8 *puts)   //串口数据发送函数
  50. {
  51.         for(; *puts !=0;  puts++)     //遇到停止符0结束
  52.         {
  53.                 S2BUF = *puts;
  54.                 B_TX2_Busy=1;
  55.                 while(B_TX2_Busy);
  56.         }
  57. }
  58. //1.发送OPEN\r\n打开数码管,数码管显示“----”
  59. //2.发送CLOSE\r\n打开数码管,数码管全部熄灭
  60. void Usart2_RunTask(void)
  61. {
  62.         if( B_RX2_OK == 1 )
  63.         {
  64.                 B_RX2_OK = 0;
  65.                 Uart2_SendStr( "接收成功!\r\n" );
  66.         }
  67. //        if( Rec_Num >= 6 )                //是否接收到了6位以上的数据
  68. //        {
  69. //                if(( Rec_Dat[Rec_Num-1] == '\n' ) && ( Rec_Dat[Rec_Num-2] == '\r' ) )        //末尾判断
  70. //                {
  71. //                        if( ( Rec_Dat[Rec_Num-6] == 'O' ) && ( Rec_Dat[Rec_Num-5] == 'P' ) && ( Rec_Dat[Rec_Num-4] == 'E' ) && ( Rec_Dat[Rec_Num-3] == 'N' )  )
  72. //                        {
  73. //                                passward[0] = 16;
  74. //                                passward[1] = 16;
  75. //                                passward[2] = 16;
  76. //                                passward[3] = 16;
  77. //                                Uart2_SendStr( "打开成功!\r\n" );
  78. //                        }
  79. //                        else if( ( Rec_Dat[Rec_Num-7] == 'C' ) && ( Rec_Dat[Rec_Num-6] == 'L' ) && ( Rec_Dat[Rec_Num-5] == 'O' ) && ( Rec_Dat[Rec_Num-4] == 'S' ) && ( Rec_Dat[Rec_Num-3] == 'E' )  )
  80. //                        {
  81. //                                passward[0] = 17;
  82. //                                passward[1] = 17;
  83. //                                passward[2] = 17;
  84. //                                passward[3] = 17;
  85. //                                Uart2_SendStr( "关闭成功!\r\n" );
  86. //                        }
  87. //                        Rec_Num = 0;
  88. //                }
  89. //        }
  90. }
复制代码


AI8051U实验箱第18集学习手敲代码串口的高级应用.zip

431.76 KB, 下载次数: 34

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:9
  • 最近打卡:2025-04-30 11:37:57
已绑定手机

6

主题

33

回帖

280

积分

版主

积分
280
发表于 2025-3-11 13:40:54 | 显示全部楼层
第19集 ADC,已手敲代码,测试通过
任务1:编写ADC读取函数,并在数码管显示当前ADC数值
截图202503111337542233.jpg

任务2 :编写ADC按键读取函数,并在数码管上显示当前按键号
截图202503111339555474.jpg

  1. #include "adc.h"
  2. void AdcSetRate(void)                //50KSPS@24.000MHz
  3. {
  4.         ADCCFG &= ~0x0f;
  5.         ADCCFG |= 0x04;                        //SPEED(4)
  6.         ADCTIM = 0xbf;                        //CSSETUP(1), CSHOLD(1), SMPDUTY(31)
  7. }
  8. void ADC_Init(void)
  9. {
  10.         //1.初始化IO为高祖输入
  11.         P1M0 &= ~0x01; P1M1 |= 0x01;
  12.         //2.初始化ADC速度
  13.         AdcSetRate();
  14.         
  15.         //3.对齐模式
  16.         ADCCFG |= 0x20;
  17.         
  18.         //4.打开ADC电源
  19.         ADC_POWER = 1;
  20. }
  21. u16 ADC_Read(u8 no)
  22. {
  23.         u16 adcval = 0;
  24.         ADC_CONTR &= 0Xf0;                //清空低四位
  25.         ADC_CONTR |= no;
  26.         
  27.         ADC_START = 1;                        //启动ADC转化
  28.         _nop_();
  29.         _nop_();
  30.         while( !ADC_FLAG );                //等待采集完成
  31.         ADC_FLAG = 0;                        //手动清空
  32.         
  33.         adcval = (((u16)ADC_RES) << 8) + (ADC_RESL);        //获取到最终的ADC数值
  34.         
  35.         return adcval;
  36. }
  37. //   (256-64) - (256+64)
  38. //   (512-64) - (512+64)
  39. #define ADC_OFFEST 64
  40. u8 ADC_KEY_READ( u16 adc )        //返回值1-16分别对应16个按键
  41. {
  42.         u16 i;
  43.         // 1.判断当前有没有按键按下
  44.         if(  adc < (256 - ADC_OFFEST) )
  45.         {
  46.                 return 0;
  47.         }
  48.         else                                                        //按键按下了
  49.         {
  50.                 for( i=1;i<=16;i++ )
  51.                 {
  52.                         if(( adc >= ( i*256-ADC_OFFEST ) ) &&( adc <= ( i*256+ADC_OFFEST )))
  53.                         {
  54.                                 return i;
  55.                         }
  56.                 }
  57.         }
  58.         return 0;
  59. }
复制代码





AI8051U实验箱第19集学习手敲代码ADC.zip

238.99 KB, 下载次数: 28

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:9
  • 最近打卡:2025-04-30 11:37:57
已绑定手机

6

主题

33

回帖

280

积分

版主

积分
280
发表于 2025-3-13 14:36:51 | 显示全部楼层
第20集 ADC_NTC测温,已手敲代码,测试通过
任务1:ADC采集NTC换算内温度
截图202503131437511297.jpg

  1. #include "adc.h"
  2. void AdcSetRate(void)                //50KSPS@24.000MHz
  3. {
  4.         ADCCFG &= ~0x0f;
  5.         ADCCFG |= 0x04;                        //SPEED(4)
  6.         ADCTIM = 0xbf;                        //CSSETUP(1), CSHOLD(1), SMPDUTY(31)
  7. }
  8. void ADC_Init(void)
  9. {
  10.         P5M0 |= 0x02; P5M1 &= ~0x02;
  11.     P51 = 1;
  12.         
  13.         //1.初始化IO为高祖输入
  14.         P1M0 &= ~0x01; P1M1 |= 0x01;
  15.     P1M0 &= ~0x08; P1M1 |= 0x08;
  16.         //2.初始化ADC速度
  17.         AdcSetRate();
  18.         
  19.         //3.对齐模式
  20.         ADCCFG |= 0x20;
  21.         
  22.         //4.打开ADC电源
  23.         ADC_POWER = 1;
  24. }
  25. u16 ADC_Read(u8 no)
  26. {
  27.         u16 adcval = 0;
  28.         ADC_CONTR &= 0Xf0;                //清空低四位
  29.         ADC_CONTR |= no;
  30.         
  31.         ADC_START = 1;                        //启动ADC转化
  32.         _nop_();
  33.         _nop_();
  34.         while( !ADC_FLAG );                //等待采集完成
  35.         ADC_FLAG = 0;                        //手动清空
  36.         
  37.         adcval = (((u16)ADC_RES) << 8) + (ADC_RESL);        //获取到最终的ADC数值
  38.         
  39.         return adcval;
  40. }
  41. //   (256-64) - (256+64)
  42. //   (512-64) - (512+64)
  43. #define ADC_OFFEST 64
  44. u8 ADC_KEY_READ( u16 adc )        //返回值1-16分别对应16个按键
  45. {
  46.         u16 i;
  47.         // 1.判断当前有没有按键按下
  48.         if(  adc < (256 - ADC_OFFEST) )
  49.         {
  50.                 return 0;
  51.         }
  52.         else                                                        //按键按下了
  53.         {
  54.                 for( i=1;i<=16;i++ )
  55.                 {
  56.                         if(( adc >= ( i*256-ADC_OFFEST ) ) &&( adc <= ( i*256+ADC_OFFEST )))
  57.                         {
  58.                                 return i;
  59.                         }
  60.                 }
  61.         }
  62.         return 0;
  63. }
  64. u16 code Temp_Tab[]=
  65. {
  66. 140 ,
  67. 149 ,
  68. 159 ,
  69. 168 ,
  70. 178 ,
  71. 188 ,
  72. 199 ,
  73. 210 ,
  74. 222 ,
  75. 233 ,
  76. 246 ,
  77. 259 ,
  78. 272 ,
  79. 286 ,
  80. 301 ,
  81. 317 ,
  82. 333 ,
  83. 349 ,
  84. 367 ,
  85. 385 ,
  86. 403 ,
  87. 423 ,
  88. 443 ,
  89. 464 ,
  90. 486 ,
  91. 509 ,
  92. 533 ,
  93. 558 ,
  94. 583 ,
  95. 610 ,
  96. 638 ,
  97. 667 ,
  98. 696 ,
  99. 727 ,
  100. 758 ,
  101. 791 ,
  102. 824 ,
  103. 858 ,
  104. 893 ,
  105. 929 ,
  106. 965 ,
  107. 1003,
  108. 1041,
  109. 1080,
  110. 1119,
  111. 1160,
  112. 1201,
  113. 1243,
  114. 1285,
  115. 1328,
  116. 1371,
  117. 1414,
  118. 1459,
  119. 1503,
  120. 1548,
  121. 1593,
  122. 1638,
  123. 1684,
  124. 1730,
  125. 1775,
  126. 1821,
  127. 1867,
  128. 1912,
  129. 1958,
  130. 2003,
  131. 2048,
  132. 2093,
  133. 2137,
  134. 2182,
  135. 2225,
  136. 2269,
  137. 2312,
  138. 2354,
  139. 2397,
  140. 2438,
  141. 2479,
  142. 2519,
  143. 2559,
  144. 2598,
  145. 2637,
  146. 2675,
  147. 2712,
  148. 2748,
  149. 2784,
  150. 2819,
  151. 2853,
  152. 2887,
  153. 2920,
  154. 2952,
  155. 2984,
  156. 3014,
  157. 3044,
  158. 3073,
  159. 3102,
  160. 3130,
  161. 3157,
  162. 3183,
  163. 3209,
  164. 3234,
  165. 3259,
  166. 3283,
  167. 3306,
  168. 3328,
  169. 3351,
  170. 3372,
  171. 3393,
  172. 3413,
  173. 3432,
  174. 3452,
  175. 3470,
  176. 3488,
  177. 3506,
  178. 3523,
  179. 3539,
  180. 3555,
  181. 3571,
  182. 3586,
  183. 3601,
  184. 3615,
  185. 3628,
  186. 3642,
  187. 3655,
  188. 3667,
  189. 3679,
  190. 3691,
  191. 3702,
  192. 3714,
  193. 3724,
  194. 3735,
  195. 3745,
  196. 3754,
  197. 3764,
  198. 3773,
  199. 3782,
  200. 3791,
  201. 3799,
  202. 3807,
  203. 3815,
  204. 3822,
  205. 3830,
  206. 3837,
  207. 3844,
  208. 3850,
  209. 3857,
  210. 3863,
  211. 3869,
  212. 3875,
  213. 3881,
  214. 3887,
  215. 3892,
  216. 3897,
  217. 3902,
  218. 3907,
  219. 3912,
  220. 3917,
  221. 3921,
  222. 3926,
  223. 3930,
  224. 3934,
  225. 3938,
  226. 3942,
  227. };  
  228. u16 Temp_Cal(u16 adc)   //返回结果是放大10倍的数值16.9*10=169
  229. {
  230.         u8 j = 0;
  231.         u16 k = 0;
  232.         u16 min;            //当前的位置
  233.         u16 max;            //当前最大的位置
  234.         u16 i;              //温度
  235.         
  236.         adc = 4096- adc;    //得到当前的adc数值
  237.         
  238.         if( adc <Temp_Tab[0])       //温度最小值检测
  239.                 return 0xfffe;
  240.         if( adc >Temp_Tab[160])      //温度最大值检测
  241.                 return 0xffff;
  242.         
  243.         min = 0;
  244.         max = 160;
  245.         
  246.         for( j=0;j<5;j++ )           //实现五次二分法查询
  247.         {
  248.                 k = (min+max)/2;
  249.                 if( adc <=Temp_Tab[k])
  250.                         max = k;
  251.                 else
  252.                         min = k;
  253.         }
  254.         
  255.         if( adc == Temp_Tab[min])
  256.                 i=min*10;
  257.         else if( adc == Temp_Tab[max])
  258.                 i=max*10;
  259.         else
  260.         {
  261.             while(min<=max)
  262.                 {
  263.                         min++;
  264.                         if(Temp_Tab[min] == adc)
  265.                         {
  266.                                 i=min*10;
  267.                                 break;
  268.                         }
  269.                         else if(  adc< Temp_Tab[min]  )   //超过这一档的温度的adc
  270.                         {
  271.                                 min --;
  272.                                 i=Temp_Tab[min];             //上一档的adc数值记下来
  273.                                 j=Temp_Tab[min+1]-Temp_Tab[min]; //这2档之间的差值
  274.                                 j=(adc-i)*10/j;
  275.                                 i=min*10+j;
  276.                                 break;
  277.                         }
  278.                 }
  279.         }
  280.         return i;
  281. }
复制代码
任务2:使用ADC测量内部1.19V信号源,反推电源电压
截图202503131438581130.jpg
截图202503131439134076.jpg
  1. #include "config.h"
  2. #include "task.h"
  3. #include "io.h"
  4. #include "tim.h"
  5. #include "18b20.h"
  6. #include "adc.h"
  7. char *USER_DEVICEDESC = NULL;
  8. char *USER_PRODUCTDESC = NULL;
  9. char *USER_STCISPCMD = "@STCISP#";
  10. void Delay3000ms(void)        //@24.000MHz
  11. {
  12.         unsigned long edata i;
  13.         _nop_();
  14.         _nop_();
  15.         i = 17999998UL;
  16.         while (i) i--;
  17. }
  18. void main(void)
  19. {
  20.         Sys_init();                                                                                //系统初始化
  21.         usb_init();                                     //USB CDC 接口配置
  22.     IE2 |= 0x80;                                    //使能USB中断
  23.         Timer0_Init();                                                                        //定时器初始化
  24.         Init_595();
  25.         Timer1_Init();
  26.         ADC_Init();
  27.        
  28.     EA = 1;                                                                                        //IE |= 0X80;
  29.        
  30.         P40 = 0;
  31.        
  32.         while (DeviceState != DEVSTATE_CONFIGURED);     //等待USB完成配置
  33.        
  34.         while(1)
  35.         {
  36.                
  37.         if (bUsbOutReady)                                                        //如果接收到了数据
  38.         {
  39.             //USB_SendData(UsbOutBuffer,OutNumber);   //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
  40.                        
  41.             usb_OUT_done();                                                        //
  42.         }
  43.                 Task_Pro_Handler_Callback();                                //执行功能函数
  44.                
  45.                 SEG_Show_U32((4096*119/(u32)ADC_Read(15)) );
  46.         }
  47. }
  48. void Timer0_Isr(void) interrupt 1                //1MS执行一次
  49. {
  50.         Task_Marks_Handler_Callback();                                        //系统计时
  51. }
复制代码

AI8051U实验箱第20集学习手敲代码ADC测温.zip

491.21 KB, 下载次数: 22

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:9
  • 最近打卡:2025-04-30 11:37:57
已绑定手机

6

主题

33

回帖

280

积分

版主

积分
280
发表于 2025-3-25 10:13:15 | 显示全部楼层
第21集 Flash模拟eeprom,已手敲代码,测试通过
截图202503251010311038.jpg

  1. #include "eeprom.h"
  2. #define         MAIN_Fosc  24000000UL
  3. #define     IAP_STANDBY()   IAP_CMD = 0     //IAP空闲命令(禁止)
  4. #define     IAP_READ()      IAP_CMD = 1     //IAP读出命令
  5. #define     IAP_WRITE()     IAP_CMD = 2     //IAP写入命令
  6. #define     IAP_ERASE()     IAP_CMD = 3     //IAP擦除命令
  7. #define     IAP_ENABLE()    IAP_CONTR = IAP_EN; IAP_TPS = MAIN_Fosc / 1000000
  8. #define     IAP_DISABLE()   IAP_CONTR = 0; IAP_CMD = 0; IAP_TRIG = 0; IAP_ADDRE = 0xff; IAP_ADDRH = 0xff; IAP_ADDRL = 0xff
  9. #define IAP_EN          (1<<7)
  10. #define IAP_SWBS        (1<<6)
  11. #define IAP_SWRST       (1<<5)
  12. #define IAP_CMD_FAIL    (1<<4)
  13. //========================================================================
  14. // 函数: void DisableEEPROM(void)
  15. // 描述: 禁止EEPROM.
  16. // 参数: none.
  17. // 返回: none.
  18. // 版本: V1.0, 2014-6-30
  19. //========================================================================
  20. void DisableEEPROM(void)        //禁止访问EEPROM
  21. {
  22.     IAP_CONTR = 0;          //关闭 IAP 功能
  23.     IAP_CMD = 0;            //清除命令寄存器
  24.     IAP_TRIG = 0;           //清除触发寄存器
  25.     IAP_ADDRE = 0xff;       //将地址设置到非 IAP 区域
  26.     IAP_ADDRH = 0xff;       //将地址设置到非 IAP 区域
  27.     IAP_ADDRL = 0xff;
  28. }
  29. //========================================================================
  30. // 函数: void EEPROM_Trig(void)
  31. // 描述: 触发EEPROM操作.
  32. // 参数: none.
  33. // 返回: none.
  34. // 版本: V1.0, 2014-6-30
  35. //========================================================================
  36. void EEPROM_Trig(void)
  37. {
  38.     F0 = EA;    //保存全局中断
  39.     EA = 0;     //禁止中断, 避免触发命令无效
  40.     IAP_TRIG = 0x5A;
  41.     IAP_TRIG = 0xA5;    //先送5AH,再送A5H到IAP触发寄存器,每次都需要如此
  42.                         //送完A5H后,IAP命令立即被触发启动
  43.                         //CPU等待IAP完成后,才会继续执行程序。
  44.     _nop_();   //多级流水线的指令系统,触发命令后建议加4个NOP,保证IAP_DATA的数据完成准备
  45.     _nop_();
  46.     _nop_();
  47.     _nop_();
  48.     EA = F0;    //恢复全局中断
  49. }
  50. //========================================================================
  51. // 函数: void EEPROM_SectorErase(u32 EE_address)
  52. // 描述: 擦除一个扇区.
  53. // 参数: EE_address:  要擦除的EEPROM的扇区中的一个字节地址.
  54. // 返回: none.
  55. // 版本: V1.0, 2014-6-30
  56. //========================================================================
  57. void EEPROM_SectorErase(u32 EE_address)
  58. {
  59.     IAP_ENABLE();                       //设置等待时间,允许IAP操作,送一次就够
  60.     IAP_ERASE();                        //宏调用, 送扇区擦除命令,命令不需改变时,不需重新送命令
  61.                                         //只有扇区擦除,没有字节擦除,512字节/扇区。
  62.                                         //扇区中任意一个字节地址都是扇区地址。
  63.     IAP_ADDRE = (u8)(EE_address >> 16); //送扇区地址高字节(地址需要改变时才需重新送地址)
  64.     IAP_ADDRH = (u8)(EE_address >> 8);  //送扇区地址中字节(地址需要改变时才需重新送地址)
  65.     IAP_ADDRL = (u8)EE_address;         //送扇区地址低字节(地址需要改变时才需重新送地址)
  66.     EEPROM_Trig();                      //触发EEPROM操作
  67.     DisableEEPROM();                    //禁止EEPROM操作
  68. }
  69. //========================================================================
  70. // 函数: void EEPROM_read_n(u32 EE_address,u8 *DataAddress,u8 lenth)
  71. // 描述: 读N个字节函数.
  72. // 参数: EE_address:  要读出的EEPROM的首地址.
  73. //       DataAddress: 要读出数据的指针.
  74. //       length:      要读出的长度
  75. // 返回: 0: 写入正确.  1: 写入长度为0错误.  2: 写入数据错误.
  76. // 版本: V1.0, 2014-6-30
  77. //========================================================================
  78. void EEPROM_read_n(u32 EE_address,u8 *DataAddress,u8 length)
  79. {
  80.     IAP_ENABLE();                           //设置等待时间,允许IAP操作,送一次就够
  81.     IAP_READ();                             //送字节读命令,命令不需改变时,不需重新送命令
  82.     do
  83.     {
  84.         IAP_ADDRE = (u8)(EE_address >> 16); //送地址高字节(地址需要改变时才需重新送地址)
  85.         IAP_ADDRH = (u8)(EE_address >> 8);  //送地址中字节(地址需要改变时才需重新送地址)
  86.         IAP_ADDRL = (u8)EE_address;         //送地址低字节(地址需要改变时才需重新送地址)
  87.         EEPROM_Trig();                      //触发EEPROM操作
  88.         *DataAddress = IAP_DATA;            //读出的数据送往
  89.         EE_address++;
  90.         DataAddress++;
  91.     }while(--length);
  92.     DisableEEPROM();
  93. }
  94. //========================================================================
  95. // 函数: u8 EEPROM_write_n(u32 EE_address,u8 *DataAddress,u8 length)
  96. // 描述: 写N个字节函数.
  97. // 参数: EE_address:  要写入的EEPROM的首地址.
  98. //       DataAddress: 要写入数据的指针.
  99. //       length:      要写入的长度
  100. // 返回: 0: 写入正确.  1: 写入长度为0错误.  2: 写入数据错误.
  101. // 版本: V1.0, 2014-6-30
  102. //========================================================================
  103. u8 EEPROM_write_n(u32 EE_address,u8 *DataAddress,u8 length)
  104. {
  105.     u8  i;
  106.     u16 j;
  107.     u8  *p;
  108.    
  109.     if(length == 0) return 1;   //长度为0错误
  110.     IAP_ENABLE();                       //设置等待时间,允许IAP操作,送一次就够
  111.     i = length;
  112.     j = EE_address;
  113.     p = DataAddress;
  114.     IAP_WRITE();                            //宏调用, 送字节写命令
  115.     do
  116.     {
  117.         IAP_ADDRE = (u8)(EE_address >> 16); //送地址高字节(地址需要改变时才需重新送地址)
  118.         IAP_ADDRH = (u8)(EE_address >> 8);  //送地址中字节(地址需要改变时才需重新送地址)
  119.         IAP_ADDRL = (u8)EE_address;         //送地址低字节(地址需要改变时才需重新送地址)
  120.         IAP_DATA  = *DataAddress;           //送数据到IAP_DATA,只有数据改变时才需重新送
  121.         EEPROM_Trig();                      //触发EEPROM操作
  122.         EE_address++;                       //下一个地址
  123.         DataAddress++;                      //下一个数据
  124.     }while(--length);                       //直到结束
  125.     EE_address = j;
  126.     length = i;
  127.     DataAddress = p;
  128.     i = 0;
  129.     IAP_READ();                             //读N个字节并比较
  130.     do
  131.     {
  132.         IAP_ADDRE = (u8)(EE_address >> 16); //送地址高字节(地址需要改变时才需重新送地址)
  133.         IAP_ADDRH = (u8)(EE_address >> 8);  //送地址中字节(地址需要改变时才需重新送地址)
  134.         IAP_ADDRL = (u8)EE_address;         //送地址低字节(地址需要改变时才需重新送地址)
  135.         EEPROM_Trig();                      //触发EEPROM操作
  136.         if(*DataAddress != IAP_DATA)        //读出的数据与源数据比较
  137.         {
  138.             i = 2;
  139.             break;
  140.         }
  141.         EE_address++;
  142.         DataAddress++;
  143.     }while(--length);
  144.     DisableEEPROM();
  145.     return i;
  146. }
  147. #define E_ADDR  10
  148. #define E_PWR        0XFE
  149. u8 SYS_Run_times = 0;
  150. //任务1:实现手册的EEPROM的基本操作,并用数码管显示当前的数值。并实现每次重新开机数值+1。
  151. void Parm_Init(void)
  152. {
  153.         u8 dat[5];                        //0:操作码   1:开机次数   2:校验码(累加校验)
  154.         
  155.         EEPROM_read_n( E_ADDR,dat,3 );
  156.         
  157.         if( dat[0] != E_PWR )                        //如果读取到的数据不为操作码,就是第一次上电,此时可以初始化
  158.         {
  159.                 EEPROM_SectorErase(E_ADDR);        //清空地址里的数据,擦除扇区
  160.                 dat[0] = E_PWR;
  161.                 dat[1] = 0;
  162.                 dat[2] = (dat[0]+dat[1]);
  163.                 EEPROM_write_n(E_ADDR,dat,3);
  164.                
  165.                 SYS_Run_times = 0;
  166.         }
  167.         else                                                        //第二次及其之后的上电
  168.         {
  169.                 if( dat[2] == (u8)(dat[0]+dat[1]) )        //校验通过,数据有效
  170.                 {
  171.                         SYS_Run_times = dat[1];
  172.                         SYS_Run_times +=1;
  173.                         EEPROM_SectorErase(E_ADDR);        //清空地址里的数据,擦除扇区
  174.                         dat[0] = E_PWR;
  175.                         dat[1] = SYS_Run_times;
  176.                         dat[2] = (dat[0]+dat[1]);
  177.                         EEPROM_write_n(E_ADDR,dat,3);                        
  178.                 }
  179.                 else
  180.                 {
  181.                         //如果数据校验出错,执行什么
  182.                 }
  183.         }
  184. }
复制代码


AI8051U实验箱第21集学习手敲代码Flash模拟EEPROM.zip

275.22 KB, 下载次数: 22

回复 支持 反对

使用道具 举报 送花

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

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-3 15:10 , Processed in 3.401464 second(s), 105 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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