基于Curiosity PIC32MX470的温湿度计+RTOS+GUI:第四步,点灯

分享到:

温湿度可以正常读取了,接下来就是调SPI和OLED显示,尝试将数据通过OLED屏显示出来。
查看OLED屏的资料,支持多种连接方式,默认的是4线SPI,但是没有MISO,也就是说OLED屏没有输出信号,不可读。那就在Information sheet上找SPI的管脚,老原因接着用用X32接口上的SPI2。为了接线方便些,用邻近的管脚作RST和DC信号
 
224729ldf7wuwfufifiwde
 
 
由于X32上只有一个3.3V,温湿度传感器最高耐压5.5V,就把它接到5V上吧,按如下方式连接OLED屏和温湿度传感器
 
2
 
接下来依然是通过MHC来使能SPI驱动
1. 打开MHC的Options选项卡,找到SPI对应的driver选项打开并做相应的配置,我的配置如下
 
3
 
4
 
2. 打开MHC的Pin Settings,将RG6、RG7、RG8、RG9设置为SPI管脚,RB8设置为DC,RD7设置为RST
 
5
 
6
 
3. 然后生成代码,主要包含以下几个源文件
 
7
 
4. 分析SPI驱动代码后可知在SYS_Initialize中已经根据用户的配置调用了SPI相关的初始化函数,所以使用时只需要在代码里直接调用drv_spi_mapping.c中的其他API就可以了。但是SPI的速率较高,我设置的是5M,如果使用中断模式,处理不好中断频繁产生的话,不知道CPU是不是吃得消;以前在SAM4N上用过轮询方式的SPI,索性将代码拿来直接用,等到调通了之后再改成中断甚至DMA看能不能处理好。先不用MHC产生的代码了,相当于只利用了它的初始化和访问硬件的PLIB库。主要的spi和ssd1306的代码如下
 
bsp_spi.c
 
void spi_select_device(PORTS_CHANNEL ch, PORTS_BIT_POS pos)
{
    SYS_PORTS_PinClear(PORTS_ID_0, ch, pos);
}
 
void spi_deselect_device(PORTS_CHANNEL ch, PORTS_BIT_POS pos)
{
    SYS_PORTS_PinSet(PORTS_ID_0, ch, pos);
}
 
static inline void spi_write_single(uint8_t data)
{
    PLIB_SPI_BufferWrite(SPI_ID_2, data);
}
 
bsp_ssd1306.c
 
#define SSD1306_SPI_INTERFACE
#define SSD1306_SPI                     SPI
 
#define SSD1306_DC_PIN_CH               PORT_CHANNEL_B
#define SSD1306_DC_PIN_POS              PORTS_BIT_POS_8
 
#define SSD1306_CS_PIN_CH               PORT_CHANNEL_G
#define SSD1306_CS_PIN_POS              PORTS_BIT_POS_9
 
#define SSD1306_RES_PIN_CH              PORT_CHANNEL_D
#define SSD1306_RES_PIN_POS             PORTS_BIT_POS_7
 
#define UG_2832HSWEG04_BAUDRATE         5000000
 
#define SSD1306_LATENCY 10
 
#define ssd1306_reset_clear()    SYS_PORTS_PinClear(PORTS_ID_0, SSD1306_RES_PIN_CH, SSD1306_RES_PIN_POS)
#define ssd1306_reset_set()      SYS_PORTS_PinSet(PORTS_ID_0, SSD1306_RES_PIN_CH, SSD1306_RES_PIN_POS)
 
// Data/CMD select, PC21Could not add reference to assembly IronPython.wpf
#define ssd1306_sel_data()       SYS_PORTS_PinSet(PORTS_ID_0, SSD1306_DC_PIN_CH, SSD1306_DC_PIN_POS)
#define ssd1306_sel_cmd()        SYS_PORTS_PinClear(PORTS_ID_0, SSD1306_DC_PIN_CH, SSD1306_DC_PIN_POS)
 
static inline void delay_us(unsigned int n)
{
    volatile uint32_t i;
    volatile uint32_t j;
 
    i = (n > 0) ? n : 1;
    for (; i > 0; i--) {
        for (j = 0; j < 100; j++) {
            ;
        }
    }
}
static inline void ssd1306_write_command(uint8_t command)
{
        spi_select_device(SSD1306_CS_PIN_CH, SSD1306_CS_PIN_POS);
        ssd1306_sel_cmd();
        spi_write_single(command);
        delay_us(SSD1306_LATENCY); // At least 3us
        spi_deselect_device(SSD1306_CS_PIN_CH, SSD1306_CS_PIN_POS);
}
 
static inline void ssd1306_write_data(uint8_t data)
{
        spi_select_device(SSD1306_CS_PIN_CH, SSD1306_CS_PIN_POS);
        ssd1306_sel_data();
        spi_write_single(data);
        delay_us(SSD1306_LATENCY); // At least 3us
        spi_deselect_device(SSD1306_CS_PIN_CH, SSD1306_CS_PIN_POS);
}
 
static inline void ssd1306_hard_reset(void)
{
        ssd1306_reset_clear();
        delay_us(SSD1306_LATENCY); // At least 3us
        ssd1306_reset_set();
        delay_us(SSD1306_LATENCY); // At least 3us
}
 
static inline void ssd1306_set_page_address(uint8_t address)
{
        // Make sure that the address is 4 bits (only 8 pages)
        address &= 0x0F;
        ssd1306_write_command(SSD1306_CMD_SET_PAGE_START_ADDRESS(address));
}
 
static inline void ssd1306_set_column_address(uint8_t address)
{
        // Make sure the address is 7 bits
        address &= 0x7F;
        ssd1306_write_command(SSD1306_CMD_SET_HIGH_COL(address >> 4));
        ssd1306_write_command(SSD1306_CMD_SET_LOW_COL(address & 0x0F));
}
 
static inline void ssd1306_clear(void)
{
        uint8_t page = 0;
        uint8_t col = 0;
 
        for (page = 0; page < 8; ++page)
        {
                ssd1306_set_page_address(page);
                ssd1306_set_column_address(0);
                for (col = 0; col < 128; ++col)
                {
                        ssd1306_write_data(0x00);
                }
        }
}
 
void ssd1306_init(void)
{
        // Do a hard reset of the OLED display controller
        ssd1306_hard_reset();
 
        // Initialize the interface
        ssd1306_interface_init();
 
        // 1/32 Duty (0x0F~0x3F)
        ssd1306_write_command(SSD1306_CMD_SET_MULTIPLEX_RATIO);
        ssd1306_write_command(0x3F);
 
        // Shift Mapping RAM Counter (0x00~0x3F)
        ssd1306_write_command(SSD1306_CMD_SET_DISPLAY_OFFSET);
        ssd1306_write_command(0x00);
 
        // Set Mapping RAM Display Start Line (0x00~0x3F)
        ssd1306_write_command(SSD1306_CMD_SET_START_LINE(0x00));
 
        // Set Column Address 0 Mapped to SEG0
        ssd1306_write_command(SSD1306_CMD_SET_SEGMENT_RE_MAP_COL127_SEG0);
 
        // Set COM/Row Scan Scan from COM63 to 0
        ssd1306_write_command(SSD1306_CMD_SET_COM_OUTPUT_SCAN_DOWN);
 
        // Set COM Pins hardware configuration
        ssd1306_write_command(SSD1306_CMD_SET_COM_PINS);
        ssd1306_write_command(0x12);
 
        ssd1306_set_contrast(0x8F);
 
        // Disable Entire display On
        ssd1306_write_command(SSD1306_CMD_ENTIRE_DISPLAY_AND_GDDRAM_ON);
 
        ssd1306_display_invert_disable();
 
        // Set Display Clock Divide Ratio / Oscillator Frequency (Default => 0x80)
        ssd1306_write_command(SSD1306_CMD_SET_DISPLAY_CLOCK_DIVIDE_RATIO);
        ssd1306_write_command(0x80);
 
        // Enable charge pump regulator
        ssd1306_write_command(SSD1306_CMD_SET_CHARGE_PUMP_SETTING);
        ssd1306_write_command(0x14);
 
        // Set VCOMH Deselect Level
        ssd1306_write_command(SSD1306_CMD_SET_VCOMH_DESELECT_LEVEL);
        ssd1306_write_command(0x40); // Default => 0x20 (0.77*VCC)
 
        // Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
        ssd1306_write_command(SSD1306_CMD_SET_PRE_CHARGE_PERIOD);
        ssd1306_write_command(0xF1);
 
        ssd1306_display_on();
}
 
void ssd1306_write_text(const char *string)
{
        uint8_t *char_ptr;
        uint8_t i;
 
        while (*string != 0) {
                if (*string < 0x7F) {
                        char_ptr = font_table[*string - 32];
                        for (i = 1; i <= char_ptr[0]; i++) {
                                ssd1306_write_data(char_ptr[i]);
                        }
                        ssd1306_write_data(0x00);
                }
                        string++;
        }
}
 
5. 最后在APP_Tasks中初始化ssd1306,把原先读温湿度操作之后的串口打印,改成显示数据,每秒读一次并通过OLED屏显示出来
 
8
 
调试还算顺利,OLED显示如下
 
9
 
虽然显示的终端由串口改成了OLED屏,但换个马甲依然无法掩饰它的简陋。下一步就是移植μGUI装一回大尾巴狼,哈哈哈
 
继续阅读
51单片机、AVR单片机和PIC单片机IO口的操作

51单片机、AVR单片机和PIC单片机IO口结构的均不同,导致了IO口操作也不同。操作单片机IO口的目的是让单片机的管脚输出逻辑电平和读取单片机管脚的逻辑电平。下面我们来看看51单片机、AVR单片机和PIC单片机IO口的操作的方法。

Curiosity PIC32MX470+简单测试 +点亮LED灯

我这次拿到的板子是PIC32MX470 Curiosity开发板,第一次使用,就先来点个LED灯吧。使用定时器中断来实现,亮灭时间各一秒。

用Curiosity PIC32MX470驱动OLED12864显示屏

这次要测试的是驱动OLED12864显示屏。OLED12864模块使用的是IIC接口,SDA接RF4引脚,SCL接RF5引脚,电源为3.3V。IIC时序使用软件模拟,采用强制读写模式。

PIC单片机12864汉字液晶模块显示文字

本文是用PIC单片机12864汉字液晶模块来显示文字

项目分享:基于PIC32MM Curiosity的超级电容器

级电容器的应用非常广泛,电动车起步、加速,给HIFI做电源,点焊机等。这次分享的项目,是超级电容器充电控制。

©2018 Microchip Corporation
facebook google plus twitter linkedin youku weibo rss