找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5534|回复: 1
收起左侧

基于STC12C2520AD单片机的50W-LED可调光灯盘控制器程序

[复制链接]
ID:76127 发表于 2015-4-5 00:35 | 显示全部楼层 |阅读模式
本帖最后由 das 于 2015-4-5 00:36 编辑
  1. //*************************************************************************************//
  2. //--P3.4口采样过零信号,每10ms采样到一个过零高电平,用于PWM0的时钟信号--//
  3. //--P1.2口采样电位器的输出调光电压,并进行8bit的A/D转换--//
  4. /*P3.7口输出PWM信号,PWM信号的频率和相位角应该自动能根据P1.6口的过零信号和P1.2口的模拟信号,
  5. 进行计算分析,输出时实的控制信号,以控制可控硅的导通时间,达到调光的目的;  */
  6. /*P3.2口利用外部中断功能,实现红外线遥控器的解码,以实现遥控功能. */
  7. //P1.6是AT24C01的数据端;P1.7是AT24C01的时钟端,用于存储红外摇器的解码值,达到记忆亮度的效果//
  8. //P1.0接LED指示灯//
  9. //       2013-9-13 /杨旭
  10. //*************************************************************************************//
  11. #include <stc12c2052ad.h>
  12. #include <intrins.h>
  13. #define uchar unsigned char
  14. #define uint  unsigned int
  15. sbit LED=P1^0;
  16. sbit IR_RE=P3^2;
  17. sbit SDA=P1^6; //AT24C01数据端
  18. sbit SCL=P1^7; //AT24C01时钟端
  19. //--------------------------------红外线解码用变量
  20. static uchar date[]={0,0,0,0};
  21. static uchar qinlong;
  22. //--------------------------------AD转换用变量
  23. static uchar AD_dat_over0,AD_dat_over1;
  24. static uchar j=0; //AD中断计数器
  25. //--------------------------------------------------------------------------/
  26. void delayms(uint a)
  27. {
  28. uint b;
  29. for(b=0;b<a;b++);
  30. }
  31. //--------------------------------------------------------------------------//
  32. void delay882()
  33. {
  34. uchar i,j;
  35. i=35;
  36. do{j=68;
  37.    do{j--;}
  38.    while(j);
  39.    i--;
  40.   }while(i);
  41. }
  42. //-------------------------
  43. void delay1000()
  44. {
  45. uchar i,j;
  46. i=39;
  47. do{j=70;
  48.    do{j--;}
  49.    while(j);
  50.    i--;
  51.   }while(i);
  52. }
  53. //-------------------------
  54. void delay2400()
  55. {
  56. uchar i,j;
  57. i=93;
  58. do{j=70;
  59.    do{j--;}
  60.    while(j);
  61.    i--;
  62.   }while(i);
  63. }
  64. //--------------------------------------------------------------------------//
  65. /*名称:初始化端口程序
  66.   功能:系统初始化,检测芯片运行
  67. */
  68. /*********************初始化LED程序******************************************/
  69. void int_LED(void)  //LED闪烁3次表示初始化正常
  70. {
  71. uchar a;
  72. for(a=0;a<3;a++)
  73. {
  74.   LED=0;
  75.   delayms(1000);
  76.   LED=1;
  77. }
  78. }
  79. //--------------------初始化端口程序-----------------------------------------/
  80. void int_cushi(void)
  81. {
  82. P1=1;
  83. P3=1;
  84. int_LED();
  85. }
  86. //--------------------------------------------------------------------------//
  87. /*名称:EEROM通信程序
  88.   功能:完成摸拟I2C功能,完成AT24C01的读和写操作
  89. */
  90. //----------
  91. void delay()
  92. { ; ; }
  93. //----------
  94. void start()//启始信号
  95. {
  96. SDA=1;
  97. delay();
  98. SCL=1;
  99. delay();
  100. SDA=0;
  101. delay();
  102. }
  103. //----------
  104. void stop()//终止信号
  105. {
  106. SDA=0;
  107. delay();
  108. SCL=1;
  109. delay();
  110. SDA=1;
  111. delay();
  112. }
  113. //----------
  114. void respons() //应答信号,等待或者发送一个应答信号
  115. {
  116. uchar i;
  117. SCL=1;
  118. delay();
  119. while((SDA==1)&&(i<250))i++;
  120. SCL=0;
  121. delay();
  122. }
  123. //----------
  124. void I2C_init()//初始化
  125. {
  126. SDA=1;
  127. SCL=1;
  128. }
  129. //----------
  130. void write_byte(uchar date)//写一字节
  131. {
  132. uchar i;
  133. SCL=0;
  134. for(i=0;i<8;i++)
  135. {
  136.   date=date<<1;
  137.   SDA=CY;
  138.   SCL=1;
  139.   delay();
  140.   SCL=0;
  141.   delay();
  142. }
  143. }
  144. //----------
  145. uchar read_byte() //读数据(也就是接收从器件传来的数据)
  146. {
  147.   uchar i,k;
  148. for(i=0;i<8;i++)
  149. {
  150.   SCL=1;
  151.   delay();
  152.   k=(k<<1)|SDA;
  153.   SCL=0;
  154.   delay();
  155. }
  156. return k;
  157. }
  158. //----------
  159. void delay1(uchar x)
  160. {
  161. uchar a,b;
  162. for(a=x;a>0;a--)
  163.   for(b=100;b>0;b--);
  164. }
  165. //----------
  166. void write_add(uchar address,uchar date)  //写数据_调用层
  167. {
  168. start();
  169. write_byte(0xa0);  //写器件地址
  170. respons();     //应答
  171. write_byte(address); //写器件内部存储地址
  172. respons();
  173. write_byte(date); //写入数据
  174. respons();
  175. stop();    //停止
  176. }
  177. //----------
  178. read_add(uchar address) //读数据_调用层
  179. {
  180. uchar date;
  181. start();
  182. write_byte(0xa0);
  183. respons();
  184. write_byte(address);
  185. respons();
  186. //------------------
  187. start();
  188. write_byte(0xa1);
  189. respons();
  190. date=read_byte();
  191. stop();
  192. return date;
  193. }
  194. //----------
  195. uchar I2C_data()  //主函数初始化后读EEROM中的亮度值
  196. {
  197. uchar a;
  198. I2C_init();
  199. delay1(250);
  200. a=read_add(23);
  201. _nop_();
  202. _nop_();
  203. _nop_();
  204. _nop_();
  205. _nop_();
  206. return a;
  207. }
  208. //--------------------------------------------------------------------------/
  209. /*名称:系统程序设置
  210.   功能:PWM0设置,外部中断0设置,AD中断设置
  211. */
  212. void lcall_sezhi()
  213. {
  214. //-----------------------------------PWM设置
  215. CMOD=0x86; //------PCA模块PWM设置
  216. CCON=0x00; //CMOD=0X84为T0为信号源,这时将T0设置段落打开//0X80时则用12分频时钟信号
  217. CL=0x00;   //CMOD=0X86使用外部脉冲信号,从P3.4脚加入信号
  218. CH=0x00;
  219. CCAPM1=0x42;  //0X42=01000010B 允许比较器功能位P1.4脚输出PWM脉宽信号
  220. PCA_PWM1=0x00;//EPC1L和EPC1H在PWM模式下的值是0X00.
  221. CR=1; //启动计数器
  222. //====================================外部中断0设置
  223. EX0=1;   //允许外部中断0
  224. IT0=1;   //下降沿触发
  225. //====================================AD
  226. EADC_SPI=1; //允许ADC中断标志位
  227. AUXR|=0x10; //允许ADC中断
  228. P1M0=0x20;
  229. P1M1=0x00; //设置P1.2为AD输入
  230. ADC_CONTR=0xe2;
  231. _nop_();
  232. _nop_();
  233. _nop_();
  234. _nop_();
  235. //-----------------------------------------------------------------------//
  236. EA=1; //开总中断
  237. }
  238. //===============================lcall_AD====================================//
  239. void lcall_AD(void)
  240. {
  241. ADC_CONTR=0xea; //启动AD转换
  242. }
  243. //---------------------------------------------------------------------------//
  244. /*名称:红外线解码数据计算处理
  245.   功能:开/并功能,键值档位计算,EEROM存储功能,给CCAP0H和CCAP0L送值
  246. */
  247. void IR_jiema_data(void)
  248. {
  249. if(qinlong==0x00)   //0档位
  250.    {//向CCAP0H,CCAP0L输入比较器的初值,以和CL CH计数器的值进行比较实现PWM调宽
  251.     I2C_init();
  252.     delay1(250);
  253.     write_add(23,256-250);//写入EEROM地址23H,存储数据256-250
  254.     CCAP0H=(256-250);
  255.     CCAP0L=(256-250);   //给PWM0传送脉宽值
  256.     qinlong=0xff;
  257.    }
  258.     else if(qinlong==0x01)  //1档位
  259.    {
  260.     I2C_init();
  261.     delay1(250);
  262.     write_add(23,256-240);
  263.     CCAP0H=(256-240);
  264.     CCAP0L=(256-240);
  265.     qinlong=0xff;
  266.    }
  267.    else if(qinlong==0x02)  //2档位
  268.    {
  269.     I2C_init();
  270.     delay1(250);
  271.     write_add(23,256-220);
  272.     CCAP0H=(256-220);
  273.     CCAP0L=(256-220);
  274.     qinlong=0xff;
  275.    }
  276.    else if(qinlong==0x03)  //3档位
  277.    {
  278.     I2C_init();
  279.     delay1(250);
  280.     write_add(23,256-200);
  281.     CCAP0H=(256-200);
  282.     CCAP0L=(256-200);
  283.     qinlong=0xff;
  284.    }
  285.    else if(qinlong==0x04) //4档位
  286.    {
  287.     I2C_init();
  288.     delay1(250);
  289.     write_add(23,256-180);
  290.     CCAP0H=(256-180);
  291.     CCAP0L=(256-180);
  292.     qinlong=0xff;
  293.    }
  294.    else if(qinlong==0x05) //5档位
  295.    {
  296.     I2C_init();
  297.     delay1(250);
  298.     write_add(23,256-160);
  299.     CCAP0H=(256-160);
  300.     CCAP0L=(256-160);
  301.     qinlong=0xff;
  302.    }
  303.    else if(qinlong==0x06) //6档位
  304.    {
  305.     I2C_init();
  306.     delay1(250);
  307.     write_add(23,256-150);
  308.     CCAP0H=(256-150);
  309.     CCAP0L=(256-150);
  310.     qinlong=0xff;
  311.    }
  312.    else if(qinlong==0x07)  //7档位
  313.    {
  314.     I2C_init();
  315.     delay1(250);
  316.     write_add(23,256-100);
  317.     CCAP0H=(256-100);
  318.     CCAP0L=(256-100);
  319.     qinlong=0xff;
  320.    }
  321.    else if(qinlong==0x08)  //8档位
  322.    {
  323.     I2C_init();
  324.     delay1(250);
  325.     write_add(23,256-50);
  326.     CCAP0H=(256-50);
  327.     CCAP0L=(256-50);
  328.     qinlong=0xff;
  329.    }
  330.    else if(qinlong==0x09)  //9档位
  331.    {
  332.     I2C_init();
  333.     delay1(250);
  334.     write_add(23,256-10);
  335.     CCAP0H=(256-10);
  336.     CCAP0L=(256-10);
  337.     qinlong=0xff;
  338.    }
  339. }
  340. //---------------------------------------------------------------------------//
  341. /*名称:AD数码转换
  342.   功能:将电位器信号转换成8位数据,并用于EEROM存储和送入CCAP0H和CCAP0L中,从而
  343.   调节PWM0的输出
  344. */
  345. //---------------------------------------------------------------------------//
  346. void AD_jiema_data(void)
  347. {         //AD转换后的数据处理
  348. if((AD_dat_over0<(AD_dat_over1+5))&&(AD_dat_over0>(AD_dat_over1-5)))  
  349. {  //如果在范围内(+5/-5)说明没调电位器,应使用存储值
  350.     //给出+-5的范围是防止输入电压稍有变动,引起的判断错误
  351.   I2C_init();
  352.   delay1(250);
  353.   CCAP0H=read_add(23);
  354. }
  355. else
  356. {
  357.   CCAP0H=(256-AD_dat_over0); //有调动电位器,应使用电位器AD值
  358.   I2C_init();
  359.   delay1(250);
  360.   write_add(23,AD_dat_over0);  //刷新EEROM中的值
  361. }
  362. }
  363. //**********************************************************************************//
  364. /*名称:主函数
  365.   功能:完成系统的初始化和红外解码数据处理;AD转换数据处理;最终达到存储数据和调节PWM0.
  366. */
  367. //******************************主函数**********************************************//
  368. void main()
  369. {
  370. uchar a;
  371. lcall_sezhi(); //调用系统设置
  372. int_cushi();   //初始化系统检查
  373. lcall_AD();    //启动AD
  374. a=I2C_data();  //读I2C的数据
  375. while(1)
  376. {
  377.   CCAP0H=(256-a);
  378.   IR_jiema_data(); //红外解码数据处理
  379.   AD_jiema_data(); //AD数据处理
  380. }     
  381. }
  382. //***************************************************************************//
  383. /*名称:红外解码_外部中断0
  384.   功能:完成红外线的数据解码功能,解码后的数据处理由主程序中的子程序处理.
  385. */
  386. //---------------------------------------------------------------------------//
  387. void int0_hongwai() interrupt 0  using 0
  388. {
  389. uchar i,j,k,n;
  390. EX0=0;
  391. for(n=0;n<10;n++)
  392. {
  393.   delay882();
  394.   if(IR_RE==1)break;
  395. }
  396. while(IR_RE==0){};
  397. //------------------------
  398. //当遥控器持续按下则接收到一个9ms的低电平引导脉冲
  399. //以及一个2.2ms的高电平脉冲,和一个0.7ms的低电平脉冲,和一个96ms的高电平脉冲
  400. //以下是连续码的检测判断程序和4.5ms高电平判断
  401. //------------------------
  402. for(j=0;j<2;j++)
  403. {
  404.   delay2400();
  405.   if(IR_RE==0)break;
  406. }
  407. //-------------------------读取数字信号----------
  408. for(i=0;i<4;i++)
  409.   {
  410.   for(k=0;k<8;k++)
  411.   {
  412.    while(IR_RE==0){};
  413.    delay882();
  414.    if(IR_RE==0)
  415.    {
  416.           date[i]>>=1;
  417.           date[i]=date[i]|0x00;
  418.    }
  419.    else if(IR_RE==1)
  420.    {
  421.     delay1000();
  422.        date[i]>>=1;
  423.              date[i]=date[i]|0x80;//0x80=10000000b
  424.    }
  425.   }
  426.   }
  427. //-----------------------------------------------
  428. if(date[0]=~date[1])       //用户码和数据码判断
  429. {
  430.   if(date[2]=~date[3])
  431.   qinlong=date[2];
  432. }
  433.   EX0=1;
  434. }
  435. //**********************************************************//
  436. /*名称:AD转换_AD中断程序
  437.   功能:完成AD转换数据传输,并同时清零AD中断标志位
  438. */
  439. //==========================================================//
  440. void AD_DAT12() interrupt 5  using 1
  441. {
  442. EADC_SPI=0;     //允许ADC中断标志位
  443. j++;
  444. if(j==1)AD_dat_over0=ADC_DATA;   //读数据
  445. else if(j==2)
  446. {
  447.   AD_dat_over1=ADC_DATA;  //
  448.   j=0;      //计数器归零
  449. }
  450. ADC_CONTR=0xea;    //AD中断标志清零
  451. EADC_SPI=1;   
  452. }
  453. //-----------------------END File---------------------------//
复制代码


回复

使用道具 举报

ID:142383 发表于 2016-12-15 17:14 | 显示全部楼层
有仿制成功的吗?
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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