项目介绍
利用板上的电位计调节电压从0-3.3V之间变化,在OLED显示屏上以数字的方式显示电压值。
设计思路
- 电位计通过分压的方式产生0-3.3V之间变化的电压,接入树莓派Pico。
- 树莓派Pico内部的ADC对该电压进行采集,得到0-4095之间的数值。
- 经过计算以后对应到实际对应的电压值。
- 树莓派Pico通过SPI控制OLED显示屏将电压值显示出来。
流程图
硬件介绍
- 尺寸: 21mmx51mm
- 芯片:RP2040微控制器芯片
- 处理器:双核Arm Cortex-MO+最高可运行到133MHZ
- 供电电压:1.8-5.5V直流
- 工作温度:-20°C到+85°C
- 片上有加速的整型和浮点库
- 邮票孔模块可直接焊接到载板
- 使用USB存储模式进行拖拽编程
- 低功耗sleep和dormant模式
- 准确的片上时钟
- 264KB 片上SRAM
- 2MB板上QSPIFlash
- 26 GPIO管脚 (含3个模拟输入)
- 2xUART
- 2x SPI控制器
- 2 x12C控制器
- 16x PWM通道
- 1xUSB 1.1控制器以及PHY支持host和device模式
- 8x可编程1/0(PIO)状态机用于定制化外设支持
- 温度传感器
- 2个按键输入
- 4个单色LED
- 12个WS2812B RGB三色灯
- 1个姿态传感器
- 1个128*64 OLED显示屏
- 1个蜂鸣器
- 1个可调电位计(用于电压表)
- 1路音频信号输入(用于示波器)
- 8位R-2R电阻网络构成的DAC(用于DDS信号发生器)
开发环境
RP2040支持多种环境进行开发,它作为一个M0的双核芯片,第一时间想到的就是用ARM的亲儿子keil开发设计,可是树莓派官方并没有提供这一种方式,而是把类似linux的一套搬到RP2040上面了,GCC固然强大,可是使用起来还是比较折腾的,MicroPython固然简单,可是与主流的嵌入式开发相差不小,封装起来的代码使用起来很畅快,但是自己要写一个驱动就麻烦的很。不过早就有大佬实现了这个想法,在keil上搭建了RP2040的开发环境。
这里我是使用了傻孩子大佬的一个开源项目:https://github.com/GorgonMeducer/Pico_Template 。使用这个项目就能轻松的使用keil进行RP2040的开发了。部署非常简单,keil只要额外安装GorgonMeducer.perf_counter.1.9.4.pack这个包(这个包在项目里面也有提供,是一个测量运行时间的组件),就能直接打开工程使用了。
上面的项目再搭配上另一个开源项目:https://github.com/majbthrd/pico-debug/releases (将RP2040的一个核实现为DAP功能),打开后下载 pico-debug-gimmecache.uf2文件,将其烧录到RP2040里,就能利用上RP2040的一个核作为DAP去调试另一个核,让RP2040的开发方式更加接近于传统的单片机的开发方式,而且实现只需要一根USB线就完成下载与调试的功能,再也不用折腾来折腾去了。
主要代码片段及说明
初始化代码
system_init();
stdio_init_all();
adc_init();
adc_gpio_init(28);
adc_select_input(2);
OLED_Init();
OLED_ShowCHinese(0,0,0);
OLED_ShowCHinese(16,0,1);
OELD初始化代码
gpio_init(8);
gpio_set_dir(8, GPIO_OUT);
gpio_init(9);
gpio_set_dir(9, GPIO_OUT);
gpio_init(10);
gpio_set_dir(10, GPIO_OUT);
gpio_init(11);
gpio_set_dir(11, GPIO_OUT);
OLED_RST_Set();
sleep_ms(100);
OLED_RST_Clr();
sleep_ms(200);
OLED_RST_Set();
OLED_WR_Byte(0xAE,OLED_CMD);//--turn off oled panel
OLED_WR_Byte(0x00,OLED_CMD);//---set low column address
OLED_WR_Byte(0x10,OLED_CMD);//---set high column address
OLED_WR_Byte(0x40,OLED_CMD);//--set start line address Set Mapping RAM Display Start Line (0x00~0x3F)
OLED_WR_Byte(0x81,OLED_CMD);//--set contrast control register
OLED_WR_Byte(0xCF,OLED_CMD); // Set SEG Output Current Brightness
OLED_WR_Byte(0xA1,OLED_CMD);//--Set SEG/Column Mapping 0xa0���ҷ��� 0xa1����
OLED_WR_Byte(0xC8,OLED_CMD);//Set COM/Row Scan Direction 0xc0���·��� 0xc8����
OLED_WR_Byte(0xA6,OLED_CMD);//--set normal display
OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
OLED_WR_Byte(0x3f,OLED_CMD);//--1/64 duty
OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset Shift Mapping RAM Counter (0x00~0x3F)
OLED_WR_Byte(0x00,OLED_CMD);//-not offset
OLED_WR_Byte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency
OLED_WR_Byte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
OLED_WR_Byte(0xD9,OLED_CMD);//--set pre-charge period
OLED_WR_Byte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
OLED_WR_Byte(0xDA,OLED_CMD);//--set com pins hardware configuration
OLED_WR_Byte(0x12,OLED_CMD);
OLED_WR_Byte(0xDB,OLED_CMD);//--set vcomh
OLED_WR_Byte(0x40,OLED_CMD);//Set VCOM Deselect Level
OLED_WR_Byte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)
OLED_WR_Byte(0x02,OLED_CMD);//
OLED_WR_Byte(0x8D,OLED_CMD);//--set Charge Pump enable/disable
OLED_WR_Byte(0x14,OLED_CMD);//--set(0x10) disable
OLED_WR_Byte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)
OLED_WR_Byte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7)
OLED_WR_Byte(0xAF,OLED_CMD);//--turn on oled panel
OLED_WR_Byte(0xAF,OLED_CMD); /*display ON*/
OLED_Clear();
OLED_Set_Pos(0,0);
通过计算转换ADC的值到实际电压,并显示。
verf = adc_read() * 3.3 / (1<<12);
sprintf(str,":%.2fV",verf);
OLED_ShowString(32, 0, (uint8_t *)str);
sleep_ms(100);
实现的功能及图片展示
显示电压
调整到最小值
调整到最大值
未来的计划或建议
如果能把复位按键跟boot按键整合到一起,做一个一键下载的功能。使用起来将更加方便些。
希望硬禾能多多举办类似的活动。