找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 12776|回复: 10
收起左侧

51单片机驱动PS2摇杆模块用1602显示X轴Y轴Y以及Z轴。1602用6线驱动

  [复制链接]
ID:79544 发表于 2016-10-12 15:12 | 显示全部楼层 |阅读模式
51单片机驱动PS2摇杆1602显示程序(1602用6根线驱动
  1. /********************************************************
  2.         功   能:51单片机通过PS2摇杆模块驱动4个LED
  3.                                 并用1602显示
  4.                         (1602使用6根线驱动)
  5.         单片机:STC12C2052AD
  6.         晶   振:12M
  7.         注   释:摇杆的x轴接单片机P10.摇杆的Y轴接单片机P11.
  8.                         Z轴接P17
  9.         作  者:苏义江改编自网络
  10.         时  间:2016-10-12
  11. *******************************************************/

  12. #include<stc12c2052ad.h>
  13. #include<intrins.h>

  14. #define uchar unsigned char
  15. #define uint unsigned int

  16. //#define TINER_HIGH  0XFF//24M
  17. //#define TINE_LOW    0XD8

  18. #define TINER_HIGH  0XFf//12M 100us
  19. #define TINE_LOW    0X9c

  20. #define    ADC_POWER   0x80  //定义ADC电源常量
  21. #define    ADC_FLAG    0x10  //定义ADC转换结束标志位
  22. #define    ADC_START   0x08  //定义ADC转换开始控制位

  23. #define    ADC_SPEEDLL 0x00  //1080个时钟转换一次
  24. #define    ADC_SPEEDL  0x20  //810个时钟转换一次
  25. #define    ADC_SPEEDH  0x40  //540个时钟转换一次
  26. #define    ADC_SPEEDHH 0x60  //270个时钟转换一次

  27. sbit led_red   =P1^6;
  28. sbit led_green =P1^5;
  29. sbit led_blue  =P1^4;
  30. sbit led_yellow=P1^3;
  31. sbit z_zhou    =P1^7;//Z轴

  32. uchar red=0x00,green=0x00,blue=0x00,yellow=0x00;
  33. uchar counter=0;

  34. typedef struct
  35. {
  36.         char x;
  37.         char y;
  38.         char drift;
  39. }pos;
  40. pos rocker;

  41. void delay(uint t)
  42. {
  43.         uint y,i;               //定义变量       
  44.         for(y=t;t>0;t--)             //如果t大于0,t减1(外层循环)
  45.         for(i=600;i>0;i--);         //i等于600,如果i大于0,i减1
  46. }

  47. ////////STC12C5608AD转换定义在哪个IO口进行并转换//////////////
  48. uchar Read5608AD (uchar CHA)
  49. {
  50.     uchar AD_FIN=0; //存储A/D转换标志;若在函数外定义此变量则不能得到连续变化的模拟量的显示
  51. /////////以下为ADC初始化程序////////////
  52.     CHA &= 0x03;      
  53. //选择ADC的8个接口中的一个(0000 0011 清0高6位)
  54.     ADC_CONTR = ADC_SPEEDHH;  //ADC转换的速度(0XX0 0000 其中XX控制速度,请根据数据手册设置)
  55.     _nop_();
  56.     ADC_CONTR |= CHA;       //选择A/D当前通道
  57.     _nop_();
  58.     ADC_CONTR |= ADC_POWER;      //启动A/D电源(1000 0000)
  59.     delay(1);            //使输入电压达到稳定(1ms即可?
  60. /////以下为ADC执行程序///////////////////
  61.     ADC_CONTR |= ADC_START;      //启动A/D转换(0000 1000 令ADCS = 1)
  62.     _nop_();
  63.     _nop_();
  64.     _nop_();
  65.     _nop_();
  66.     while (AD_FIN ==0)         //等待A/D转换结束
  67.     {     
  68.     AD_FIN = (ADC_CONTR & ADC_FLAG); //0001 0000测试A/D转换结束否
  69.     }
  70.     ADC_CONTR &= 0xE7;      //1111 0111 清ADC_FLAG位, 关闭A/D转换,
  71.     return (ADC_DATA);          //返回A/D转换结果(8位)
  72. }
  73. /*
  74. ///////////STC12C2052AD转换//////////////
  75. uchar Read2052AD (uchar CHA)
  76. {

  77.         uchar AD_FIN=0; //存储A/D转换标志;若在函数外定义此变量则不能得到连续变化的模拟量的显示
  78. //////以下为ADC初始化程序/////////////////

  79.     CHA &= 0x07;            //选择ADC的8个接口中的一个(0000 0111 清0高5位)
  80.     ADC_CONTR = 0x60;  //ADC转换的速度(0XX0 0000 其中XX控制速度,请根据数据手册设置)
  81.    _nop_();_nop_();_nop_();
  82.     ADC_CONTR |= CHA;       //选择A/D当前通道
  83.     _nop_();_nop_();_nop_();
  84.     ADC_CONTR |= 0x80;      //启动A/D电源
  85.     delay(2);            //使输入电压达到稳定(1ms即可?
  86. //////////以下为ADC执行程序////////////////////
  87.     ADC_CONTR |= 0x08;      //启动A/D转换(0000 1000 令ADCS = 1)
  88.     _nop_();
  89.     _nop_();
  90.     _nop_();
  91.     _nop_();
  92.         _nop_();
  93.         _nop_();
  94.     while (AD_FIN ==0)
  95.         {     //等待A/D转换结束
  96.             AD_FIN = (ADC_CONTR & 0x10); //0001 0000测试A/D转换结束否
  97.     }
  98.     ADC_CONTR &= 0xE7;      //1111 0111 清ADC_FLAG位, 关闭A/D转换,
  99.         return (ADC_DATA);          //返回A/D转换结果(8位)
  100. }
  101. */
  102. pos rocker_read(int drift)
  103. {
  104.         pos buffer;
  105.         buffer.x=128-Read5608AD (1);
  106.         buffer.y=128-Read5608AD (0);
  107.         buffer.drift=drift;
  108.         return (buffer);
  109. }
  110. void timer0_init()
  111. {
  112.         TMOD=0X01;
  113.         TH0=TINER_HIGH ;
  114.         TL0=TINE_LOW;
  115.         ET0=1;
  116.         TR0=1;
  117.         EA=1;
  118. }
  119. void timer0_irpt() interrupt 1
  120. {
  121.         TH0=TINER_HIGH ;
  122.         TL0=TINE_LOW;
  123.         counter++;
  124.         if(counter<red)    led_red=0;    else led_red=1;               
  125.         if(counter<green)  led_green=0;  else led_green=1;
  126.         if(counter<blue)   led_blue=0;   else led_blue=1;
  127.         if(counter<yellow) led_yellow=0; else led_yellow=1;
  128. }
  129. //6根线驱动LCD1602接口定义              
  130. #define LCD_DB P2 // - - P2 = DB4~DB7
  131. sbit LCD_RS=P2^2; // - - p2.2 = RS
  132. //sbit LCD_RW=P0^6; // - - p2.1 = RW 接地
  133. sbit LCD_E=P2^3; // - - p2.3 = E

  134. // - - 定义子程序函数
  135. void LCD_init(void); // - - 初始化LCD1602函数
  136. void LCD_write_H4bit_command(uchar dat);
  137. void LCD_write_L4bit_command(uchar dat);
  138. void LCD_write_4bit_command(uchar command); // - - 向LCD1602写指令函数
  139. void LCD_write_4bit_data(uchar dat); // - - 向LCD1602写数据函数
  140. void LCD_set_xy(uchar x,uchar y); // - - 设置LCD1602显示位置 X(0-16),y(1-2)
  141. void LCD_disp_char(uchar x,uchar y,uchar dat); // - - 在LCD1602上显示一个字符
  142. void LCD_disp_string(uchar X,uchar Y,uchar *s); // - - 在LCD1602上显示一个字符串
  143. //void LCD_check_busy(void);//检查忙函数。我没用到此函数,因为通过率极低。
  144. void LCD_delay_10us(uint n); // - - 10微秒的延时子程序
  145. void LCD_delay_50us(uint n); // - - 50微秒的延时子程序
  146. void LCD_delay_10us(uint n) // - - 10微秒的延时子程序
  147. {
  148. uint i,j;
  149. for(i=n*10;i>0;i--) // - - 晶振及单片机修改设置
  150. for(j=2;j>0;j--);
  151. }

  152. void LCD_delay_50us(uint n) // - - 50微秒的延时子程序
  153. {
  154.         uint i,j;
  155.         for(i=n*10;i>0;i--) // - - 晶振及单片机修改设置
  156.         for(j=22;j>0;j--);
  157. }
  158. // - - 初始化LCD1602
  159. void LCD_init(void)
  160. {
  161.         LCD_delay_50us(50);
  162.         LCD_RS=0; // - - 指令
  163. //        LCD_RW=0; // - - 写入
  164.         LCD_E=0; // - - 使能
  165.         LCD_write_L4bit_command(0x03); // - - 设置4位格式,2行,5x7
  166.         LCD_delay_50us(20);       
  167.         LCD_write_L4bit_command(0x03); // - - 设置4位格式,2行,5x7
  168.         LCD_delay_50us(20);
  169.         LCD_write_L4bit_command(0x02); // - - 设置4位格式,2行,5x7
  170.         LCD_delay_50us(2);
  171.         LCD_write_4bit_command(0x28); // - - 设置4位格式,2行,5x7
  172.         LCD_delay_10us(10);
  173.         LCD_write_4bit_command(0x28); // - - 设置4位格式,2行,5x7
  174.         LCD_delay_10us(10);
  175.         LCD_write_4bit_command(0x0c); // - - 整体显示,关光标,不闪烁
  176.         LCD_delay_10us(10);
  177.         LCD_write_4bit_command(0x06); // - - 设定输入方式,增量不移位
  178.         LCD_delay_10us(10);
  179.         LCD_write_4bit_command(0x01); // - - 清除屏幕显示
  180.         LCD_delay_50us(40);
  181. }
  182. //********************************

  183. // - - 向LCD1602写指令
  184. void LCD_write_4bit_command(uchar dat)
  185. {
  186.         LCD_delay_10us(50);
  187.         LCD_RS=0; // - - 指令
  188. //        LCD_RW=0; // - - 写入
  189.         LCD_write_H4bit_command(dat);
  190.         LCD_write_L4bit_command(dat);
  191. }

  192. // - - 向LCD1602写高四位指令
  193. void LCD_write_H4bit_command(uchar dat)
  194. {
  195.         LCD_delay_10us(250);
  196.         LCD_DB=(LCD_DB&0x0F)|(dat&0xF0);
  197.         LCD_delay_10us(50);
  198.         LCD_E=1; // - - 允许
  199.         LCD_delay_10us(250);
  200.         LCD_E=0;
  201. }

  202. // - - 向LCD1602写低四位指令
  203. void LCD_write_L4bit_command(uchar dat)
  204. {
  205.         dat<<=4;
  206.         LCD_delay_10us(50);
  207.         LCD_DB=(LCD_DB&0x0F)|(dat&0xF0);
  208.         LCD_delay_10us(50);
  209.         LCD_E=1; // - - 允许
  210.         LCD_delay_10us(250);
  211.         LCD_E=0;
  212. }

  213. // - - 向LCD1602写数据
  214. void LCD_write_4bit_data(uchar dat)
  215. {
  216.         LCD_delay_10us(50);
  217.         LCD_RS=1; // - - 数据
  218. //        LCD_RW=0; // - - 写入
  219.         LCD_write_H4bit_command(dat);
  220.         LCD_write_L4bit_command(dat);
  221. }

  222. // - - 设置显示位置
  223. void LCD_set_xy(uchar x,uchar y)
  224. {
  225.         uchar address;
  226.         if(y==1)
  227.         {
  228.                 address=0x80+x; // - - 第一行位置
  229.         }
  230.         else
  231.         {
  232.                 address=0xc0+x; // - - 第二行位置
  233.         }
  234.         LCD_delay_10us(50);
  235.         LCD_write_4bit_command(address);
  236. }

  237. // - - 显示一个字符函数
  238. void LCD_disp_char(uchar x,uchar y,uchar dat)
  239. // - - LCD_disp_char(0,1,0x38); // - - 显示8
  240. {
  241.         LCD_set_xy(x,y);
  242.         LCD_delay_10us(5);
  243.         LCD_write_4bit_data(dat);
  244. }

  245. // - - 显示一个字符串函数
  246. void LCD_disp_string(uchar x,uchar y,uchar *s)
  247. {
  248.         LCD_set_xy(x,y);
  249.         LCD_delay_10us(5);
  250.         while(*s!='\0')
  251.         {
  252.                 LCD_write_4bit_data(*s);
  253.                 s++;
  254.         }
  255. }
  256. void display(uint num )//显示数字
  257. {
  258.         uchar qian,bai,shi,ge;
  259.         qian=num/1000;
  260.         bai=num%1000/100;
  261.         shi=num%100/10;
  262.         ge=num%10;
  263.         LCD_set_xy(3,0);
  264.         LCD_write_4bit_data(qian+0x30);
  265.         LCD_write_4bit_data(bai+0x30);
  266.         LCD_write_4bit_data(shi+0x30);
  267.         LCD_write_4bit_data(ge+0x30);
  268. }
  269. void display1(uint num )//显示数字
  270. {
  271.         uchar qian,bai,shi,ge;
  272.         qian=num/1000;
  273.         bai=num%1000/100;
  274.         shi=num%100/10;
  275.         ge=num%10;
  276.         LCD_set_xy(11,0);
  277.         LCD_write_4bit_data(qian+0x30);
  278.         LCD_write_4bit_data(bai+0x30);
  279.         LCD_write_4bit_data(shi+0x30);
  280.         LCD_write_4bit_data(ge+0x30);
  281. }
  282. void main()
  283. {
  284.         LCD_init();
  285.         timer0_init();
  286.         LCD_disp_string(0,0,"X=");
  287.         LCD_disp_string(8,0,"Y=");
  288.         LCD_disp_string(4,1,"Z=");
  289.         while(1)
  290.         {
  291.                 if(z_zhou==0)
  292.                 {
  293.                         LCD_disp_string(7,1,"O N");
  294.                 }
  295.                
  296.                 else
  297.                 {
  298.         //        LCD_write_4bit_command(0x01);
  299.                 LCD_disp_string(7,1,"OFF");
  300.                 }
  301.                 rocker=rocker_read(0);               
  302.                 if(rocker.x<-3)
  303.                 {
  304.                         rocker.x=-rocker.x+1;
  305.                         blue=rocker.x<<1;
  306.                         display(blue);
  307.                 }
  308.                 else
  309.                 {
  310.                         if(rocker.x>3)
  311.                         {
  312.                                 green=rocker.x<<1;
  313.                                 display(green);
  314.                         }
  315.                         else
  316.                         {
  317.                                 green=blue=0;
  318.                         }
  319.                 }
  320.                 if(rocker.y<-3)
  321.                 {
  322.                         rocker.y=-rocker.y+1;
  323.                         yellow=rocker.y<<1;
  324.                         display1(yellow);
  325.                 }
  326.                 else
  327.                 {
  328.                         if(rocker.y>3)
  329.                         {
  330.                                 red=rocker.y<<1;
  331.                                 display1(red);
  332.                         }
  333.                         else
  334.                         {
  335.                                 yellow=red=0;
  336.                         }
  337.                 }
  338.         }
  339. }
复制代码


评分

参与人数 1黑币 +100 收起 理由
admin + 100 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:140343 发表于 2016-10-12 15:26 | 显示全部楼层
这个好,PS2摇杆也可以用于我们的单片机diy了,不知道楼主的ps2摇杆的型号是什么?所有的摇杆都可以用这个方法来驱动吗?
回复

使用道具 举报

ID:147475 发表于 2017-1-16 10:04 | 显示全部楼层
大侠,请问我把程序用到我的板子上(80c51)怎么不行,是AD程序不一样吗?
回复

使用道具 举报

ID:171735 发表于 2017-3-18 11:12 | 显示全部楼层
木子乔 发表于 2017-1-16 10:04
大侠,请问我把程序用到我的板子上(80c51)怎么不行,是AD程序不一样吗?

这个程序的Ad是stc12单片机内部自带的AD,80C51没有内部AD,所以用不了。
回复

使用道具 举报

ID:232956 发表于 2018-2-1 16:59 | 显示全部楼层
请问可以用stc12c5a16s2代替吗?  都是12系列的应该可以吧?
回复

使用道具 举报

ID:286699 发表于 2018-3-7 13:22 | 显示全部楼层
zeng10119 发表于 2017-3-18 11:12
这个程序的Ad是stc12单片机内部自带的AD,80C51没有内部AD,所以用不了。

楼主你好~这个x,y轴出来的是模拟量的电压值吗?  也就是在89c51上接一个PCF8591这样一个A/D转换模块就好了吧
回复

使用道具 举报

ID:242932 发表于 2018-8-5 14:00 | 显示全部楼层
666666666
回复

使用道具 举报

ID:383138 发表于 2018-8-5 16:16 | 显示全部楼层
加个按键记录和按键循环自动输出会更实用
回复

使用道具 举报

ID:380389 发表于 2018-8-6 06:40 来自手机 | 显示全部楼层
感谢楼主分享
回复

使用道具 举报

ID:492472 发表于 2019-7-16 21:41 | 显示全部楼层
楼主还在吗?
回复

使用道具 举报

ID:155987 发表于 2020-4-22 16:55 | 显示全部楼层
编译下都是问题
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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