imx6ul+spi使用

一、准备工作
这次准备用天嵌的板子点个oled屏幕,spi总线的,然而看原理图,可用的io没有。
所以得先释放资源,把led的两个io用来驱动res,dc脚,spi用的是板子上的spi1。
SPI1_MOSI接oled的data
SPI1_SCLK接oled的sclk

现在释放驱动:
make menuconfig
Device Drivers  --->
     [ ] LED Support  ----  
然后保存,退出。从新编译,把zImage更新到板子上。
用下面指令测试你的IO是否释放;
echo 130 > /sys/class/gpio/export
如果在目录下成功的导出一个gpio130文件夹就说明成功了。

现在板子的实验环境是:文件系统是通过nfs挂载linux服务器上的文件系统,具体操作看我的nfs挂载贴。
二、开始写oled驱动;
本来打算简简单单写,但是写着写着发现要写的代码太多了。于是决定写个库,参考了友善的库,真是非常感谢学到了很多。
下面是库的结构:

还学了一波makefile真的很得劲,欢迎小伙伴一起开源一起学习。

下面是oled的主程序:
int main(int argc, char** argv)
{
        int dc_pin = 0, res_pin = 0;
        int dev_fd = 0;

        /* imx系列板子io_port要减1 */
        if ((res_pin = convert_gpio_pin("GPIO4_02")) == -1 || (dc_pin  = convert_gpio_pin("GPIO4_07")) == -1) {
                printf("convert_gpio_pin error\n");
                return -1;
        } else {
                printf("res_pin = %d, dc_pi = %d\n ", res_pin, dc_pin);
        }
        if ((dev_fd = oled_init(dc_pin, res_pin)) == -1) {
                printf("oled_init error!\n");
                return -1;
        }
        oled_clean_screen(dev_fd);
        oled_disp_8x16str(dev_fd, 0, 0, "Sourcelink");
        oled_disp_8x16str(dev_fd, 0, 16, "Sourcelink");
        oled_deinit(dev_fd);
        return 0;        
}

1) 进行gpio转换,把原理图的gpio转换成linux下的gpio
2)初始化oled
3) 清屏,并显示
4)释放io和spi资源

1)gpio转换很简单,看源码吧
EXPORT int convert_gpio_pin(const char *pin_str)
{
        const char *ppin = pin_str;
        unsigned char port = 0;
        unsigned char pin = 0;
        char pin_buf[5] = {0};
        if (strlen(ppin) !=  8) {
                printf("please use GPIOx_xx\n");
                return -1;
        }
        int ret = -1;
        if (strncmp(ppin, "GPIO", 4) != 0) {
                ret = -1;        
        } else {
                ppin += 4;
                port = *ppin;
                if (port >= 'A' && port <= 'G') {
                        port -= 'A';
                } else if (port >= '0' && port <= '6') {
                        port -= '0';
                } else {
                        return -1;
                }
                ppin++;
                if (*ppin == '_') {
                         ppin++;
                         strncat(pin_buf, ppin, 2);
                         pin = atoi(pin_buf);
                }        
                ret = port * 32 + pin;
        }        
        return ret;
}

2)oled初始化
EXPORT int oled_init(int dc_pin, int res_pin)
{
        int dev_fd;
        int ret = 0;
               
        sig_dc_pin  = dc_pin;
        sig_res_pin = res_pin;

        if ((dev_fd = open_hardware(SPI1_PATH, O_RDWR)) < 0) {
        printf("Fail to open SPI device\n");
        return -1;
    }
        if ((ret = oled_spi_init(dev_fd)) == -1) {
                printf("Fail to init oled_spi\n");
        }
        #if 1
        if (export_gpio_pin(sig_dc_pin) || export_gpio_pin(sig_res_pin)) {
                printf("Fail to request resetPin or DCPin\n");
        }
        if ((ret =oled_reset() == -1)) {
                printf("fail to reset oled\n");
        }

        oled_write_cmd(dev_fd, 0xae);//--turn off oled panel
    oled_write_cmd(dev_fd, 0x00);//---set low column address
    oled_write_cmd(dev_fd, 0x10);//---set high column address
    oled_write_cmd(dev_fd, 0x40);//--set start line address  Set Mapping RAM Display       Start Line (0x00~0x3F)
    oled_write_cmd(dev_fd, 0x81);//--set contrast control register
    oled_write_cmd(dev_fd, 0xcf); // Set SEG Output Current Brightness
    oled_write_cmd(dev_fd, 0xa1);//--Set SEG/Column Mapping     0xa0宸﹀彸鍙嶇疆 0xa1姝e父
    oled_write_cmd(dev_fd, 0xc8);//Set COM/Row Scan Direction   0xc0涓婁笅鍙嶇疆 0xc8姝e父
    oled_write_cmd(dev_fd, 0xa6);//--set normal display
    oled_write_cmd(dev_fd, 0xa8);//--set multiplex ratio(1 to 64)
    oled_write_cmd(dev_fd, 0x3f);//--1/64 duty
    oled_write_cmd(dev_fd, 0xd3);//-set display offset Shift Mapping RAM Counter (0x00~0x3F)
    oled_write_cmd(dev_fd, 0x00);//-not offset
    oled_write_cmd(dev_fd, 0xd5);//--set display clock divide ratio/oscillator frequency
    oled_write_cmd(dev_fd, 0x80);//--set divide ratio, Set Clock as 100 Frames/Sec
    oled_write_cmd(dev_fd, 0xd9);//--set pre-charge period
    oled_write_cmd(dev_fd, 0xf1);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
    oled_write_cmd(dev_fd, 0xda);//--set com pins hardware configuration
    oled_write_cmd(dev_fd, 0x12);
    oled_write_cmd(dev_fd, 0xdb);//--set vcomh
    oled_write_cmd(dev_fd, 0x40);//Set VCOM Deselect Level
    oled_write_cmd(dev_fd, 0x20);//-Set Page Addressing Mode (0x00/0x01/0x02)
    oled_write_cmd(dev_fd, 0x02);//
    oled_write_cmd(dev_fd, 0x8d);//--set Charge Pump enable/disable
    oled_write_cmd(dev_fd, 0x14);//--set(0x10) disable
    oled_write_cmd(dev_fd, 0xa4);// Disable Entire Display On (0xa4/0xa5)
    oled_write_cmd(dev_fd, 0xa6);// Disable Inverse Display On (0xa6/a7)
    oled_write_cmd(dev_fd, 0xaf);//--turn on oled panel

        ret = oled_set_pos(dev_fd, 0, 0);

        if (ret == 0) {
        return dev_fd;
    } else {
            printf("unexportGPIOPin\n");
        unexport_gpio_pin(sig_dc_pin);
        unexport_gpio_pin(sig_res_pin);
        return ret;
    }
#endif
}

三、实验步骤
1) 编译
写好了makefile当然是直接make下就好了。
然后把编译出来的libslhl.so和libslbsp.so拷贝到rootfs中,这两个动态库分别在lib和bsp目录下;
把demo中编译出来的可执行文件source-oled拷贝到rootfs中
2)安装动态库
因为souce-oled的运行依赖于动态库,所以要在板子上把编译出来的动态库装上

mkdir -p  usr/local/lib
install --mode=644 libslhl.so /usr/local/lib
install --mode=644 libslbsp.so /usr/local/lib
3) 执行
./source-oled

下面是效果图:


在bbb上试验库的时候,发现最后不能释放res的io不然会拉低复位。


你可能感兴趣的:(linux学习过程)