本帖最后由 stm1024 于 2021-11-20 13:47 编辑
响应日天的号召,老早就立了这个flag,虽然还有很多工作没有做完,不过先做个笔记和大家分享一下,虽然还只是一个半成品,然后投入的时间也不够多,但是自己立的flag,硬着头皮也要搞下去。其实只做了一点微小的工作,有点诚惶诚恐,感觉hold不住“DIY”这么高大上的要求。
闲话少说,讲正事儿。
通过画原理图、PCB布线、打样,最后成品长这样:
哈哈,机智的小伙已经知道了这不就是某宝是几块钱的JoyStick Shield嘛。
没错,翻箱倒柜找出来的这个玩意儿,还是以前玩arduino的时候买的,现在也算是吃灰资深板卡了,选用这个的一方面是有有现成的,另外就是NXP的很多评估板都是兼容Arduino的接口,所以我可以省不少杜邦线了,而且看起来也不会那么凌乱了。
然后就是开发板了,刚开始盯上的是LPC51U68,有Arduino接口,不过对着电气原理图发现针脚有点儿对不上号,然后瞄了一下LPC54608的板子,针脚没问题。
其实这个项目需要用到的硬件资源并不多,主要是GPIO,ADC,然后就是串口、USB等,用一颗LPC11U68等芯片也可以实现(话说我之前也有一块LPC11U68的板子的,只是没找到),但是画板子不是我的强项,只能捡现成的板子,而且还可以理直气壮的说自己没有重复造轮子(我也想啊,就是不会造 )。
然后看看原理图,那个JoyStick shield的电路原理图,里面带的东西还不少,支持串口,nRF21L01接口等,实际我们要的也就是那么几个按键和摇杆的数据:
板子上就是这样设计的,然后我们可以看到,左下方的是模拟量,摇杆的X和Y接入了模拟量,按键A-F,以及K在右边。
再看看LPC54608的排母:
左边分别是P0_16对应ADC0的通道4,P0_31对应ADC0的通道5,之前看LPC51U68的原理图发现不行是因为有一个模拟量采集针脚直接悬空了……右边分别是对应A-F,K就不截图了,对应的是P4_7。
这个搞完了就可以开始写代码了:
首先是按键的配置,这个简单,就是基本的GPIO操作,而且默认也是Input的,所以只需要使能GPIO的时钟就OK了。
- void ButtonInit()
- {
- SYSCON->AHBCLKCTRLSET[0]=1U<<15;//GPIO1
- SYSCON->AHBCLKCTRLSET[0]=1U<<17;//GPIO3
- SYSCON->AHBCLKCTRLSET[2]=1U<<9;//GPIO4
- }
复制代码然后是ADC0的配置:
- //ADC0 config
- void XDADC0_Init()
- {
- //Bit 6: Temp sensor
- //Bit 9: PDEN_VD2_ANA
- //Bit 10: ADC0
- //Bit 19: VDDA to the ADC
- //Bit 23: Vrefp to the ADC
- SYSCON->PDRUNCFGCLR[0]|=(1U<<6)|(1U<<9)|(1U<<10)|(1U<<19)|(1U<<23);
- //Enables the clock for the ADC0 register interface
- SYSCON->AHBCLKCTRLSET[0]=1U<<27;
- //PIN config
- //Enable clock of the IOCON
- SYSCON->AHBCLKCTRLSET[0]=(1U<<13);
- //axis-X is P0.16--ADC4 P0_16 FUNC0 as ADC0_4 P0.31@J12_2
- IOCON->PIO[0][16]=0x00|(1U<<9);
- //axis-Y is P0.31--ADC5 P0_31 FUNC0 as ADC0_5 P0.31@J12_4
- IOCON->PIO[0][31]=0x00|(1U<<9);
- //disable clock of the IOCON when finish setting to save power
- SYSCON->AHBCLKCTRLCLR[0]=(1U<<13);
- ADC0->CTRL=0x0e00;//bypass CALIB
- SysTick_DelayTicks(5);
- ADC0->STARTUP=1U<<0;//ADC_ENA
- SysTick_DelayTicks(5);
- ADC0->STARTUP|=1U<<1;//ADC_INIT
- ADC0->SEQ_CTRL[0]=0x40040000;
- SysTick_DelayTicks(5);
- //use ADC ch4 & ch5
- ADC0->SEQ_CTRL[0]=0xc0040000|(1U<<4)|(1U<<5);//enable
- }
复制代码这里使用了序列A,使能通道4和通道5。
然后是一些定义:
- //按键顺序及定义
- //A P3.2
- //B P4.5
- //C P3.10
- //D P3.14
- //E P3.1
- //F P1.22
- //KEY P4.7
- uint8_t PORTS[7]={3,4,3,3,3,1,4};
- uint8_t PINS[7]={2,5,10,14,1,22,7};
复制代码因为我打算在后面的程序中采用循环方式,所以这里直接把GPIO的PORT和PIN给定义进去,一会直接用循环遍历,简单粗暴。
最后就是按键的采集,这个地方采用轮询方式,采集按键及模拟量输入值:
- while(1)
- {
- buttons=0x00;
- for(i=0;i<7;i++)
- {
- if(GPIO->B[PORTS[i]][PINS[i]]==0)
- buttons|=1U<<i;
- }
- memset(pbuffer,0x00,256);
- sprintf(pbuffer,"JS:B=%02x,X=%02x,Y=%02x\n",buttons,XDADC0_Read(4)>>4,XDADC0_Read(5)>>4);
- Console_WriteString(pbuffer,strlen(pbuffer));
- SysTick_DelayTicks(100);
- }
复制代码先用串口输出采集到的数据,观察一波采集的效果:
目前看起来还算正常,不过测试发现按键E按下去以后没反应,然后用万用表测试了一下E端口和GND之间的通断,发现是正常的,这就让我有点费解了。另外一个问题是ADC采集的,ADC采集我并没有去计算具体的电压值,实际上就是把0-4095之间的值换算到了0-255之间,这样符合大多数摇杆的设置。不过有个问题是,不知道是板子做工的原因,还是供电,或者模拟量采集本身就有点不够精确,本来期望的中位值是两个0x80,但是实际测试发现一个是0x7a,一个是0x7f,后面一个还好,前面一个似乎有点儿不太准确,这种情况下只能通过手工校正来补偿了。 //------------------------------------------------------
目前已经完成的工作就这些,也没啥技术含量,就是基本外设的使用。不过后面需要做的工作才是最难搞的,第一个是打算将USB外设跑起来,这样可以把数据按USB协议发送给电脑,模拟发送按键键盘,例如ABCD按键分别对应键盘的四个方向键等,还了解到windows有一些支持JoyStick的API可以鼓捣一下。还有另外一种比较low的方法,就是自己写一个基于串口的游戏,自娱自乐吧,哈哈。
|