本文主要介紹了在樹莓派的CM3+的平臺上實現gpio接口的複用功能的方法。以gpio32和gpio33實現uart1的功能爲例。以及在gpio14和gpio15上面實現uart0的方法。
硬件平臺:raspberrypi CM3+(bcm2837)
系統:2019-09-26-raspbian-buster-full
根據樹莓派的官方文檔的CM3+的datasheet得知gpio32和gpio33引腳是既可以作爲uart0也可以作爲uart1功能的:
本文主要實現的是將這兩個gpio口實現爲ALT5,也就是TXD1和RXD1功能。
通過修改樹莓派的股票GPU解析的設備數文件:dt-blob-disp1-cam2.dts
文件的下載地址:https://www.raspberrypi.org/documentation/hardware/computemodule/cmio-display.md
dts文件的修改如下:
然後在系統使用dtc工具編譯GPU解析的文件dt-blob.bin文件:
dtc -I dts -O dtb -o dt-blob.bin dt-blob-disp1-cam2.dts
將生成的dt-blob.bin文件複製到/boot目錄下。
參考:https://www.raspberrypi.org/forums/viewtopic.php?p=1442712
在/boot/cmdline.txt文件中加入:8250.nr_uarts=1
在樹莓派系統中的sudo raspi-config中打開enable serial 配置後。
重啓後的設備節點:
增加了ttyS0設備節點以及serial1。
執行時串口會 打開失敗:
繼續參考:https://github.com/agherzan/meta-raspberrypi/issues/400
在/boot/config.txt文件中加入如下的內容:
enable_uart=1
disable_splash=1
#disable_fw_kms_setup=1
dioverlay=pi3-disable-bt
dtparam=uart1=on
core_freq=250
#dtoverlay=mini-uart1
dtoverlay=uart1,txd1_pin=32,rxd1_pin=33
加入上述內容後,reboot後,可以正常的通過pin32和pin33引腳的uart1的設備節點ttyS0傳輸數據。
樹莓派系統中默認的uart0的引腳死14和15。然而,uart0串口也可以是32和33兩個引腳,如下:
如果想通過操作/dev/ttyAMA0設備節點操作其他引腳的uart0,那麼可以修改如下內容,將uart0的引腳由之前的14和15修改爲32和33。
修改dts文件dt-blob-disp1-cam2.dts如下:
然後在應用軟件中打開ttyAMA0.可以正常打開串口設備。
以下是在樹莓派系統中使用ttyAMA0和ttyS0的基於qt 串口測試代碼
#if 1
QSerialPort serial0;
//設置串口名
serial0.setPortName("ttyAMA0");//ttyAMA0
//serial0.setPortName("ttyS0");//ttyS0
//設置波特率
serial0.setBaudRate(QSerialPort::Baud115200,QSerialPort::AllDirections);
//設置數據位數
serial0.setDataBits(QSerialPort::Data8);
//設置奇偶校驗
serial0.setParity(QSerialPort::NoParity);
//設置停止位
serial0.setStopBits(QSerialPort::OneStop);
//設置流控制
serial0.setFlowControl(QSerialPort::NoFlowControl);
//打開串口
if(!serial0.open(QIODevice::ReadWrite))
{
std::cout << "serial port ttyAMA0 open failed" << std::endl;
return -1;
}
char serial0_tx_buff[10] = {0,1,2,3,4,5,6,7,8,9};
int ret = serial0.write(serial0_tx_buff, sizeof(serial0_tx_buff));
int ret1 = serial0.waitForBytesWritten(1000);
char serial0_rx_buff[50] = {0};
//usleep(10000);
int serial0_rx_len = serial0.read(serial0_rx_buff, sizeof(serial0_rx_buff));
if(serial0_rx_len > 0){
printf("read data: serial0_rx_len %d ", serial0_rx_len);
for(int i = 0; i < serial0_rx_len; i++){
printf("%02x ", serial0_rx_buff[i]);
}
printf("\n");
}
#endif