久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

我的小制作基于AVR單片機的電子時鐘

[復制鏈接]
跳轉到指定樓層
樓主
ID:72519 發表于 2015-1-21 17:42 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
通過幾天的AVR單片機學習,用AVR系列單片機中的ATMEGA16,LCD液晶屏LC1602,溫度采集模塊DS18B20,時鐘模塊DS1302,5V升壓IC,和三個按鍵,以及一些電子元件完成了數字時鐘系統的設計。在一塊液晶顯示屏上實現動態,時、分、秒、年、月、日、星期、溫度數據的顯示, 通過三個按鍵,S1調時鍵、S2時間加鍵、S3時間減鍵、實現時鐘的年、月、日、星期、時、分、秒、的調整。本系統設計大部分功能由軟件來實現,使電路簡單明了。這次制作源代碼,是從我已前的一個小制作基于51單片機的DS1302時鐘上移植過來的所以制作沒用多少時間。一開始用51單片機做這電子鐘在調試時還是出了不少問題如,沒考慮到51單片機P0口沒有內至上拉電阻,結果在硬件上加了8個10K的電阻造成硬件焊接的復雜性。因為鋰電池供電的只有3.6V左右而各種芯片要5V才正常工作,根據多年的數碼產品維修經驗用平板電板中的USB升壓電路將3.6V升成了5V。因為沒考慮這個自舉升電路的頻率很高1M到3M左右用了普通二極管做升壓中的倍壓管造成了電壓升不到5V的問題最后改用了快恢復二極管才正常工作,本次制做中的按鍵調日期功能還沒完善好,因每個月的天數都不一樣最后決定為到32時把日期變為1。通過這次的制作讓我全面的了解了單片機
相關產品的開發流程,及一些常用芯片驅動程序的編寫。始我在單片機上的學習更上一層!
  1. 附原代碼

  2. #include<iom16v.h>
  3. #include<macros.h>          //頭文件
  4. #include"delay.h"

  5. #define uchar unsigned char
  6. #define uint unsigned int

  7. #define S3_R PINA&BIT(0)
  8. #define S2_R PINA&BIT(3)
  9. #define S1_R PINA&BIT(6)

  10. #define RS_L PORTD&=~BIT(0)
  11. #define RS_H PORTD|=BIT(0)
  12. #define RS_OUT DDRD|=BIT(0)   //宏定義單片機與其它芯片的連接方便IO口的操作

  13. #define RW_L PORTD&=~BIT(1)
  14. #define RW_H PORTD|=BIT(1)
  15. #define RW_OUT DDRD|=BIT(1)

  16. #define EN_L PORTD&=~BIT(2)
  17. #define EN_H PORTD|=BIT(2)
  18. #define EN_OUT DDRD|=BIT(2)

  19. #define IO_L PORTB&=~BIT(5)
  20. #define IO_H PORTB|=BIT(5)
  21. #define IO_OUT DDRB|=BIT(5)
  22. #define IO_R PINB&BIT(5)
  23. #define IO_IN DDRB&=~BIT(5)

  24. #define SCK_L PORTB&=~BIT(6)
  25. #define SCK_H PORTB|=BIT(6)
  26. #define SCK_OUT DDRB|=BIT(6)

  27. #define RST_L PORTB&=~BIT(7)
  28. #define RST_H PORTB|=BIT(7)    //宏定義單片機與其它芯片的連接方便IO口的操作
  29. #define RST_OUT DDRB|=BIT(7)

  30. #define DQ_L PORTD&=~BIT(7)
  31. #define DQ_H PORTD|=BIT(7)
  32. #define DQ_OUT DDRD|=BIT(7)
  33. #define DQ_R PIND&BIT(7)
  34. #define DQ_IN DDRD&=~BIT(7)

  35. uchar tab4[]={0x82,0x85,0x88,0x8f,0xc0,0xc3,0xc6};//用來存放年月日星期時分秒的地址
  36. uchar write_add[7]={0x8c,0x88,0x86,0x8a,0x84,0x82,0x80}; //寫寄存器地址
  37. uchar read_add[7]={0x8d,0x89,0x87,0x8b,0x85,0x83,0x81};//存放從1302中讀數寄存器地址
  38. uchar tab1[]="20  -  -   week  ";  //屏上要固定顯示的字符
  39. uchar tab2[]="  :  :  ";//屏上要固定顯示的字符
  40. uchar tab3[];
  41. uchar tab[]={12,2,4,5,5,5,5};//年 月 日 周 時 分 秒的初值
  42. char tung;//根據tung確定按鍵位置不能定成uchar型
  43. void write_1602com(uchar com);//1602寫地址函數
  44. void init_1602(void);//1602初始化
  45. void write_1302bvte(uchar);//1302寫數據函數
  46. uchar read_1302(uchar);//1302讀數據函數
  47. void write_1302(uchar,uchar);//1302指定地址定數據函數
  48. void write_ds1302_1();//時間顯示函數
  49. void read_1302_1();//一次讀出年月日 時分秒
  50. void flx(uchar j);  //時間轉顯示函數
  51. void key(void); //按鍵函數
  52. void set_rtc(void); //一次設置初始時間年月日函數
  53. void init_18b20(void);//18b20初始化函數
  54. void write_18b20(uchar value);//ds18b20寫數據函數
  55. uchar read_18b20(void);//讀溫度函數
  56. uchar readtemperature(void);//一次性讀出溫度
  57. void xianshi(void);//溫度顯示函數

  58. void init_18b20(void)
  59. {
  60.    DQ_OUT;
  61.    DQ_L;
  62.    delay_100us(5);
  63.    DQ_H;                    //初始化18B20
  64.    delay_100us(5);
  65. }
  66. void write_18b20(uchar value)
  67. {
  68.   uchar i;
  69.   for(i=0;i<8;i++)
  70.   {
  71.      DQ_OUT;
  72.      DQ_L;           //寫一位函數
  73.   delay_10us();
  74.   if(value&0x01)//
  75.   {
  76.      DQ_H;
  77.   }
  78.   }
  79.   delay_100us(1);
  80.   DQ_H;
  81.   value=value>>1;
  82. }
  83. uchar read_18b20(void)
  84. {
  85.   uchar i,value;
  86.   for(i=0;i<8;i++)
  87. {
  88. value=value>>1;
  89. DQ_OUT;
  90. DQ_L;
  91. delay_10us();//讀一位函數
  92. DQ_H;
  93. DQ_IN;
  94. if(DQ_R)
  95. {
  96.    value|=0x80;
  97. }
  98.    delay_50us();
  99. }
  100.   return value;
  101. }

  102. uchar readtemperature(void)//一次性讀出溫度
  103. {
  104. uint i,j;//一定要用int型j大于256
  105. init_18b20;
  106. write_18b20(0xcc);//跳過ROM
  107. write_18b20(0x44);//啟動溫度測量
  108. delay_100us(20);
  109. init_18b20();
  110. write_18b20(0xcc);
  111. write_18b20(0xbe);//讀取溫度
  112. i=read_18b20();//低位
  113. j=read_18b20();//高位
  114. i=i>>4;    //因不用小數部分所以移4位
  115. j=j*16+i; //將存放低8位的和高8位合到一塊
  116.   return j ;
  117. }
  118. void xianshi(void)
  119. {
  120.    uint temp,k,f;
  121.    temp=readtemperature();//將溫度保存到temp中
  122.    f=temp/10;  //分離出十位跟個位
  123.    k=temp%10;
  124.    write_1602com(0x80+0x40+10);//溫度顯示的位置
  125.    write_1602dat(f+0x30);
  126.    write_1602dat(k+0x30); //將溫度寫到1602中

  127. }
  128. void set_rtc(void) //一次設置初始時間年月日函數
  129. {
  130.    uchar i,j;
  131.    for(i=0;i<7;i++)
  132.    {
  133.      j=tab[i]/10; //將設置的年月日時分解出十位放入J中
  134.      tab3[i]=tab[i]%10; //將設置的年月日時間分解出個位再放入time_data[]數組中
  135.      tab3[i]=tab3[i]+j*16;//將十進制的個位和十位轉換為BCD碼
  136.    }
  137.    write_1302(0x8e,0x00);//去除寫保護
  138.    for(i=0;i<7;i++)
  139.    {
  140.      write_1302(write_add[i],tab3[i]); //寫要設置初始時間日期的操作寄存器的地址
  141.    }
  142.    write_1302(0x8e,0x80);//加寫保護
  143. }
  144. void key(void)
  145. {  
  146.    uchar s1,s2,s3;
  147.    if(~S1_R) //如果S1按下
  148.    {
  149.      delay_1ms(3); //延時去抖
  150.      if(~S1_R)  
  151.      {
  152. while(~S1_R);   //
  153.         tung=0;  //tung用來確定光標的位置
  154. while(tung<=6) //循環7次   時分秒年月日星期
  155. {  
  156.   if(~S2_R)
  157.   {
  158.     delay_1ms(3);
  159.   if(~S2_R)//去抖動延時
  160.   {
  161. while(~S2_R);    // 檢測按鍵是否放開
  162. tab[tung]++; //如果+鍵按下加1
  163.       }
  164. }
  165. if(~S3_R)
  166. {
  167.    delay_1ms(3); // 檢測按鍵是否放開
  168.    if(~S3_R)
  169. {
  170. while(~S3_R);  //按鍵是否松手
  171. tab[tung]--;  //如果—鍵按下減1
  172. }
  173. }  

  174. switch(tung)
  175. { //通過tung的值確定光標的位置
  176. case 0:
  177.   if(tab[tung]<3)  //如果tung=0;則表示正在調年讓年在2004到2098這個范圍內
  178.   tab[tung]=98;
  179.   if(tab[tung]>98)
  180.   tab[tung]=4;
  181.   break;
  182.   
  183. case 1:
  184.   if(tab[tung]<1)
  185.    tab[tung]=12;
  186.   if(tab[tung]>12)  //如果tung=1;則表示正在調月讓月在1到12這個范圍內
  187.     tab[tung]=1;
  188.    break;
  189. case 2:
  190.   if(tab[tung]==0)
  191.    tab[tung]=31;
  192.   if(tab[tung]==32)   //如果tung=2;則表示正在調日讓在1到31這個范圍內
  193.    tab[tung]=1;
  194.   break;
  195. case 3:
  196. if(tab[tung]<1)
  197.   tab[tung]=7;
  198. if(tab[tung]>7)   //如果tung =3則表示下在調星期讓在1到7這個范圍內
  199.   tab[tung]=1;
  200.   break;
  201. case 4:
  202. if(tab[tung]<0)
  203.      tab[tung]=23;
  204. if(tab[tung]>23) //如果tung=4則表示在調時讓時在1到23這個范圍內
  205.   tab[tung]=0;
  206.    break;
  207. case 5:
  208. if(tab[tung]<0)
  209.   tab[tung]=59;
  210. if(tab[tung]>59)   //如果tung=5;則表示正在調分讓分在1到59這個范圍內
  211.   tab[tung]=0;
  212.    break;
  213. default:
  214. if(tab[tung]<0)
  215.   tab[tung]=59;
  216. if(tab[tung]>59)   //如果tung=6;則表示正在調秒讓秒在1到59這個范圍內
  217.   tab[tung]=0;
  218.    break;
  219. }
  220. write_1602com(tab4[tung]); //顯示正在調的位置  
  221. flx(tab[tung]);    //將數據分離成1602的顯示碼并送到1602顯示屏


  222. if(~S1_R)
  223. {
  224. while(~S1_R);  //判斷是否調好了時間如果好了則跳出key
  225. tung++; //每按一下S1調式模式鍵則加一次如果到了7次跳出KEY函數
  226. }

  227. }

  228. }
  229. write_1602com(0x0c);//調完了時間關閉光標
  230. set_rtc(); //把調好的時間數據送到DS1302芯片中
  231. }
  232. }


  233. void flx(uchar j)
  234. {  
  235. uchar k,a;
  236. write_1602com(0x0f);  //開光標顯示指令
  237. k=j/10;   //分離十位跟個位
  238. a=j%10;
  239. if(tung!=3) //年月日時分秒分離
  240. {

  241.      write_1602dat(k+0x30);  //將分離的十位跟個位換成LC1602能顯示的碼
  242. write_1602com(0x0c);//關光標指令   
  243.      write_1602dat(a+0x30);

  244. }
  245. else

  246. write_1602dat(a+0x30); //星期分離
  247.   
  248. }

  249. void read_1302_1(void)//一次讀出年月日 時分秒函數
  250. {
  251. uchar i,shi,ge,tun;
  252. for(i=0;i<7;i++)
  253. {
  254. tun=read_1302(read_add[i]);  //一次將年月日從DS1302中讀出送到數組中
  255. ge=tun%16;
  256. shi=tun/16;    //將BCD碼分成十位和個位
  257. tab[i]=shi*10+ge; //再換成十進制存到數組tab中

  258. }
  259. }
  260. void write_ds1302_1()
  261. {
  262.     read_1302_1();//一次讀出年月日 時分秒函數  
  263.    write_1602com(0x80+0x40+6);//秒的位置
  264. write_1602dat(tab[6]/10+0x30);
  265. write_1602dat(tab[6]%10+0x30);

  266. write_1602com(0x80+0x40+3);//
  267. write_1602dat(tab[5]/10+0x30); //分的位置
  268. write_1602dat(tab[5]%10+0x30);
  269.   //將十進制的數據換成1602的顯示碼送到顯示屏
  270. write_1602com(0x80+0x40+0);// //時的地址
  271. write_1602dat(tab[4]/10+0x30);   //顯示屏的第二排要加0x80+40
  272. write_1602dat(tab[4]%10+0x30);

  273. write_1602com(0x80+2);//
  274. write_1602dat(tab[0]/10+0x30);//年的地址
  275. write_1602dat(tab[0]%10+0x30);

  276. write_1602com(0x80+5);// 顯示屏 的第一排地址要加0x80;
  277. write_1602dat(tab[1]/10+0x30);
  278. write_1602dat(tab[1]%10+0x30); //月的地址

  279. write_1602com(0x80+8);//   日的地址
  280. write_1602dat(tab[2]/10+0x30);
  281. write_1602dat(tab[2]%10+0x30);

  282. write_1602com(0x80+15);    //星期的地址
  283. write_1602dat(tab[3]%10+0x30);
  284. }
  285. void init_1302(void)
  286. {
  287.   SCK_OUT;
  288.   RST_OUT;//1302IO口初始化
  289. }

  290. void write_1302(uchar dat ,uchar add)
  291. {
  292.    RST_L;
  293.    SCK_L;
  294.    RST_H;
  295.    write_1302bvte(dat);//指定地址寫數據函數
  296.    write_1302bvte(add);
  297.    RST_L;
  298.    SCK_H;
  299. }
  300. void write_1302bvte(uchar add)
  301. {
  302.   uchar i;
  303.   RST_L;
  304.   SCK_L;
  305.   IO_OUT;
  306.   delay_1ms(2);
  307.   RST_H;
  308.   for(i=0;i<8;i++)
  309.   {
  310.    if(add&0X01)
  311.    {
  312.     IO_H;        //1302寫函數
  313.    }
  314.    else
  315.    {
  316.     IO_L;
  317.    }
  318.    SCK_H;
  319.    SCK_L;
  320.    add=add>>1;
  321.    }
  322.   }
  323. uchar read_1302(uchar dat)
  324. {
  325.   uchar i,byte;
  326.   write_1302bvte(dat);
  327.   IO_IN;
  328.   for(i=0;i<8;i++)
  329.   {
  330.     byte=byte>>1;
  331.     if(IO_R)
  332.     {                  //1302讀數據函數

  333.      byte=byte|0x80;
  334.     }
  335.     SCK_H;
  336.     SCK_L;
  337.   }
  338.   RST_L;
  339. return byte;
  340. }


  341. void write_1602com(uchar com)
  342. {
  343. RS_L;
  344. RW_L;    //寫指令函數
  345. PORTC=com;
  346. EN_H;
  347. delay_1ms(4);
  348.     EN_L;
  349. }
  350. void write_1602dat(uchar dat)
  351. {
  352. RS_H;
  353. RW_L;
  354.     PORTC=dat;
  355.     EN_H;                //寫數據函數
  356. delay_1ms(4);
  357. EN_L;

  358. }
  359. void init_1602(void)
  360. {  
  361.    uchar tou;
  362.     DDRC=0XFF;
  363. PORTC=0;
  364. RS_OUT;
  365. RW_OUT;
  366. EN_OUT;
  367. EN_L;
  368. write_1602com(0x38);//
  369. write_1602com(0x0C);//  //1602初始化函數
  370. write_1602com(0x06);
  371. write_1602com(0x01);
  372. write_1602com(0x80);
  373.     write_1602com(0x80);  //第一行顯示的位置地址
  374.     for(tou=0;tou<16;tou++)
  375. {
  376. write_1602dat(tab1[tou]);  //顯示固定字符
  377. }
  378.     write_1602com(0x80+0x40); //第二行顯示的位置地址
  379.     for(tou=0;tou<8;tou++)
  380.     {
  381. write_1602dat(tab2[tou]);
  382. }
  383.     write_1602com(0x80+0x40+12);   
  384.     write_1602dat(0xdf);//顯示溫度的小圓圈符號,0xdf是液晶屏字符庫的該符號地址碼
  385.     write_1602dat(0x43); //顯示"C"符號,0x43是液晶屏字符庫里大寫C的地址碼 */
  386. }

  387. void main(void)
  388. {
  389.   DDRA&=~0X49;//按鍵初始化
  390.   PORTA|=0X49;

  391.   init_1602();
  392.   init_1302();
  393. while(1)
  394. {
  395.     xianshi();//溫度顯示函數
  396.    write_ds1302_1();//時間顯示函數
  397.    key();//按鍵函數
  398. }
  399. }

  400. =0X49;

  401.   init_1602();
  402.   init_1302();
  403. while(1)
  404. {
  405.     xianshi();//溫度顯示函數
  406.    write_ds1302_1();//時間顯示函數
  407.    key();//按鍵函數
  408. }
  409. }

復制代碼



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

使用道具 舉報

沙發
ID:81954 發表于 2015-6-3 20:36 | 只看該作者
為何不能運行呢
回復

使用道具 舉報

板凳
ID:82588 發表于 2015-6-10 10:19 | 只看該作者
收藏了,正打算也練下手,來一個,做完和你的對比一下
回復

使用道具 舉報

地板
ID:87088 發表于 2015-7-28 17:19 | 只看該作者
程序已經保存下來了,稍后學習一下,謝謝樓主分享。
回復

使用道具 舉報

5#
ID:210328 發表于 2017-6-14 16:49 | 只看該作者
為啥運行有錯誤?
回復

使用道具 舉報

6#
ID:82765 發表于 2017-6-17 12:33 | 只看該作者
提示: 作者被禁止或刪除 內容自動屏蔽
回復

使用道具 舉報

7#
ID:44037 發表于 2017-6-18 14:35 | 只看該作者
謝謝樓主分享。學習一下
回復

使用道具 舉報

8#
ID:210328 發表于 2017-6-18 23:40 | 只看該作者
cjjcjj1 發表于 2017-6-17 12:33
具體錯誤內容是什么,貼出來看看


D:\ICCAVR\ICCAVR安裝\bin\imakew -f 222.mak
    iccavr -c -ID:\ICCAVR\ICCAVR安裝\include -e -D__ICC_VERSION=722 -DATMega16  -l -g -MLongJump -MHasMul -MEnhanced  2222.c
!E F:\期末單片機作業\程序\2222\2222.c(3): cannot include source file "delay.h"; file not found
D:\ICCAVR\ICCAVR安裝\bin\imakew.exe: Error code 1
Done: there are error(s). Exit code: 1. Sun Jun 18 23:39:26 2017
回復

使用道具 舉報

9#
ID:275398 發表于 2018-5-21 22:23 | 只看該作者
666666
回復

使用道具 舉報

10#
ID:413383 發表于 2018-10-23 22:22 | 只看該作者
AVR學習中,為何不能運行呢
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 电影午夜精品一区二区三区 | 成人在线视频免费观看 | 蜜桃黄网 | 亚洲午夜小视频 | 日韩一区二区三区在线播放 | 在线播放日韩 | 久久成人精品视频 | 中文字幕日韩在线观看 | 免费在线观看黄色av | 偷拍自拍网 | 色秀网站 | 97视频在线观看网站 | 久久久国产一区二区三区四区小说 | 操人网站 | 国产美女精品 | 国产精品999 | 日韩精品在线一区 | 玖玖视频网 | 国产1区 | 国产精品极品美女在线观看免费 | 美日韩免费视频 | 国产精品久久久久久亚洲调教 | 九七午夜剧场福利写真 | 一二三四在线视频观看社区 | 日韩免费成人av | 欧美视频 亚洲视频 | 日本三级电影在线观看视频 | h免费观看 | 日本激情视频在线播放 | 成人精品国产 | 亚洲欧美在线观看 | 91av在线视频观看 | 婷婷一级片 | 国产97在线 | 日韩 | 97av在线| 综合色久 | 日韩成人性视频 | 日韩成人影院在线观看 | 国产精品久久久久久久久久久久 | 久久精品一区二区三区四区 | 男人天堂视频在线观看 |