RP2040 CXX SDK PIO应用例程
RP2040 CXX SDK PIO应用例程
- 📍DS18B20 PIO参考项目例程:
https://github.com/jondurrant/RP2040PIO-DS18B20
- 📍DHT11 PIO 参考项目例程:
https://github.com/vmilea/pico_dht
在官方的SDK pico-examples中有关PIO的例程有20个:https://github.com/raspberrypi/pico-examples
📗RP2040 PIO功能介绍
📝RP2040中有2个相同的PIO块。每个PIO模块都有到总线结构、GPIO和中断控制器的专用连接。单个PIO模块的示意图如图38所示:
- ✨使用PIO功能模拟外设,需要使用PIO专门的汇编指令集进行编程。
- 📑PIO指令集:
不懂得汇编的,只能先拿现有PIO开发出来的模拟驱动外设模块,直接使用。我们不需要了解驱动模块内部是如何实现的。RP2040只集成了2路PIO资源,一般只能用来模拟单线或双线的信号。
📘DS18B20 PIO驱动例程
- 📍例程项目:
https://github.com/jondurrant/RP2040PIO-DS18B20
- DS1820.PIO引脚7。
- 工程结构:
- 🔖
CMakeLists.txt
相关内容:
set(PICO_CXX_ENABLE_EXCEPTIONS 1) # Enable C++ exceptions
add_executable(RP2040_PIO_DS18B20RP2040_PIO_DS18B20.cppDS18B20.hDS18B20.cpp)
# Add any user requested libraries
pico_generate_pio_header(RP2040_PIO_DS18B20 ${CMAKE_CURRENT_LIST_DIR}/DS1820.pio)
- 程序
/*CMSIS-DAP烧录命令:openocd -f interface/cmsis-dap.cfg -f target/rp2040.cfg -c "adapter speed 5000"-c "program RP2040_PIO_DS18B20.elf verify reset exit"jlink命令: openocd -f interface/jlink.cfg -f target/rp2040.cfg -c "adapter speed 2000" -c "program RP2040_PIO_DS18B20.elf verify reset exit"
*/#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/pio.h"
#include "hardware/clocks.h"
#include "DS1820.pio.h"
#include "pico/time.h"
#include "DS18B20.h"
#include "hardware/adc.h"//读取内部温度需要#define BUILTIN_LED PICO_DEFAULT_LED_PIN // LED is on the same pin as the default LED 25
#define DS18B20_PIN 7
#define DS18B20_PIO pio0
//芯片内部温度读取函数
float getTemp(){const float conversion_factor = 3.3f / (1 << 12);adc_select_input(4);float v = (float)adc_read() * conversion_factor;float t = 27.0 - ((v - 0.706)/0.001721);return t;
}int main()
{uint32_t time;float temp;DS18B20 ds = DS18B20(DS18B20_PIO, DS18B20_PIN);stdio_init_all();//setup_default_uart();gpio_init(BUILTIN_LED);gpio_set_dir(BUILTIN_LED, GPIO_OUT);gpio_pull_up(BUILTIN_LED);adc_init();adc_set_temp_sensor_enabled(true);sleep_ms(3000);printf("GO\n");while (1) {time = to_ms_since_boot (get_absolute_time ());ds.convert();time = to_ms_since_boot (get_absolute_time ()) - time;printf("Covert time %d ms \n", time);sleep_ms(1000);time = to_ms_since_boot (get_absolute_time ());temp = ds.getTemperature();time = to_ms_since_boot (get_absolute_time ()) - time;printf("DS18B20 Temp %f in %d ms\r\n", temp, time);printf("Pico Temp was %f\n", getTemp());sleep_ms(500);gpio_xor_mask(1ul << BUILTIN_LED); // Toggle the LED}return 0;
}
📘DHT11 PIO驱动例程
- 📍dht11驱动例程参考:
https://github.com/vmilea/pico_dht
- 🔖DHT11.PIO引脚7。
- 🍁工程结构:
- 🔖
CMakeLists.txt
相关内容:
add_subdirectory(dht)
# Add executable. Default name is the project name, version 0.1add_executable(RP2040_DHT11_PIO RP2040_DHT11_PIO.cdht/dht.c)
# Add any user requested libraries
pico_generate_pio_header(RP2040_DHT11_PIO ${CMAKE_CURRENT_LIST_DIR}/dht/dht.pio)# Add the standard library to the build
target_link_libraries(RP2040_DHT11_PIOpico_stdlibhardware_adchardware_piohardware_gpiohardware_dma)# Add the standard include files to the build
target_include_directories(RP2040_DHT11_PIO PRIVATE${CMAKE_CURRENT_LIST_DIR}${CMAKE_CURRENT_LIST_DIR}/.. # for our common lwipopts or any other standard includes, if required${CMAKE_CURRENT_LIST_DIR}/dht/include
)
- 📝程序:
/*CMSIS-DAP烧录命令:openocd -f interface/cmsis-dap.cfg -f target/rp2040.cfg -c "adapter speed 5000"-c "program RP2040_DHT11_PIO.elf verify reset exit"jlink命令: openocd -f interface/jlink.cfg -f target/rp2040.cfg -c "adapter speed 2000" -c "program RP2040_DHT11_PIO.elf verify reset exit"*/
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/pio.h"
#include "hardware/timer.h"
#include "hardware/clocks.h"
#include "hardware/adc.h" //读取内部温度需要
#include "dht.h"#define BUILTIN_LED PICO_DEFAULT_LED_PIN // LED is on the same pin as the default LED 25// change this to match your setup
static const dht_model_t DHT_MODEL = DHT11;
static const uint DATA_PIN = 7;//DHT11数据引脚定义static float celsius_to_fahrenheit(float temperature)
{return temperature * (9.0f / 5) + 32;
}//芯片内部温度读取函数
float getTemp()
{const float conversion_factor = 3.3f / (1 << 12);adc_select_input(4);float v = (float)adc_read() * conversion_factor;float t = 27.0 - ((v - 0.706) / 0.001721);return t;
}int main()
{stdio_init_all();// setup_default_uart();gpio_init(BUILTIN_LED);gpio_set_dir(BUILTIN_LED, GPIO_OUT);gpio_pull_up(BUILTIN_LED);adc_init();adc_set_temp_sensor_enabled(true);puts("\nDHT test");dht_t dht;dht_init(&dht, DHT_MODEL, pio0, DATA_PIN, true /* pull_up */);do{dht_start_measurement(&dht);float humidity;float temperature_c;dht_result_t result = dht_finish_measurement_blocking(&dht, &humidity, &temperature_c);if (result == DHT_RESULT_OK){printf("%.1f C (%.1f F), %.1f%% humidity\n", temperature_c, celsius_to_fahrenheit(temperature_c), humidity);}else if (result == DHT_RESULT_TIMEOUT){puts("DHT sensor not responding. Please check your wiring.");}else{assert(result == DHT_RESULT_BAD_CHECKSUM);puts("Bad checksum");}printf("Pico Temp was %f\n", getTemp()); //打印芯片内部温度gpio_xor_mask(1ul << BUILTIN_LED); // Toggle the LEDsleep_ms(2000);} while (true);return 0;
}
📘PWM PIO驱动例程
- 🔖来自自带例程:
pico-examples\pio\pwm
- 📝测试代码:
#include <stdio.h>
/*CMSIS-DAP烧录命令:openocd -f interface/cmsis-dap.cfg -f target/rp2040.cfg -c "adapter speed 5000"-c "program RP2040_PIO_PWM.elf verify reset exit"jlink命令: openocd -f interface/jlink.cfg -f target/rp2040.cfg -c "adapter speed 2000" -c "program RP2040_PIO_PWM.elf verify reset exit"
Sysclk = 125MHz PIO_clk =41,667,788.8Hz
Sysclk = 270MHz PIO_clk =44,892,160Hz
PWM输出频率 = 41,667,788.8Hz / ( PWM_period+1)
*/
#include "pico/stdlib.h"
#include "hardware/pio.h"
#include "pwm.pio.h"#define BUILTIN_LED PICO_DEFAULT_LED_PIN // LED is on the same pin as the default LED 25
#define PWM_PIN 7// Write `period` to the input shift register
void pio_pwm_set_period(PIO pio, uint sm, uint32_t period)
{pio_sm_set_enabled(pio, sm, false);pio_sm_put_blocking(pio, sm, period);pio_sm_exec(pio, sm, pio_encode_pull(false, false));pio_sm_exec(pio, sm, pio_encode_out(pio_isr, 32));pio_sm_set_enabled(pio, sm, true);
}// Write `level` to TX FIFO. State machine will copy this into X.
void pio_pwm_set_level(PIO pio, uint sm, uint32_t level)
{pio_sm_put_blocking(pio, sm, level);
}int main()
{// set_sys_clock_khz(270000, true);//270000KHzstdio_init_all();// setup_default_uart();puts("PIO PWM Example");gpio_init(BUILTIN_LED);gpio_set_dir(BUILTIN_LED, GPIO_OUT);gpio_pull_up(BUILTIN_LED);// todo get free smPIO pio = pio0;int sm = 0;uint offset = pio_add_program(pio, &pwm_program);printf("Loaded program at %d\n", offset);pwm_program_init(pio, sm, offset, PWM_PIN);// pio_pwm_set_period(pio, sm, (1u << 16) - 1); // 65535pio_pwm_set_period(pio, sm, 4167 - 1);int level = 4166/2;//32768;// printf("Level = %d\n", level);pio_pwm_set_level(pio, sm, level);// level = (level + 1) % 256;while (true){printf("Level = %d\n", level);sleep_ms(1000);gpio_xor_mask(1ul << BUILTIN_LED); // Toggle the LED}return 0;
}
- 📏PWM输出10KHz.占空比:50%
- 🎉超频情况下:
set_sys_clock_khz(270000, true);//270000KHz
- 🌿也就是说通过PIO 产生的PWM输出频率,在没有超频的情况下。RP2040默认时钟频率125MHz情况下,PWM输出最大频率:41,667,788Hz / ( 1+1)=20,833,894Hz
- 🌿时钟频率超频到270MHz情况下,PWM输出最大频率:44,892,160/2=22,446,080Hz