Git例程源码仓库:https://github.com/ZhiliangMa/raspberry.git
使用树莓派的串口前,需要先了解树莓派板载的两个串口的区别:
树莓派3为了增加蓝牙硬件,将独立时钟的硬件串口(/dev/ttyAMA0),默认分配给了蓝牙。
与CPU共用时钟的硬件串口(/dev/ttyS0),默认分配给了15、16。
而树莓派的CPU时钟不像单片机一般是固定的,而是根据负载来动态调整的,这就会导致有些问题:当CPU频率切换时,可能会造成串口有乱码现象。说人话就是 /dev/ttyAMA0更加稳定。
本节先讲 /dev/ttyS0 串口的用法,适用于对稳定性要求不是很严苛,但绝对能满足绝大部分需求的场合。
/dev/ttyAMA0 挖坑留给下一节。
左上角的树莓图标 Menu - Preferences - Raspberry Pi Configuration
Serial Port 勾上 Enable,Serial Console 勾 Disable。之后需要重启,点击 YES。
重启后进入终端,ls /dev/ttyS*,如显示 /dev/ttyS0 则正确。
使用时需要添加 #include
函数语句 | 函数功能 |
int serialOpen (char *device, const int baud) | 打开 *device设备地址的串口,波特率 baud |
void serialClose(int fd) | 关闭 fd关联的串口 |
void serialFlush (int fd) | 清空串行缓冲区(TX和RX) |
void serialPutchar(int fd, unsigned char c) | 通过串口发送一个字节的数据 |
void serialPuts (int fd, char *s) | 通过串口发送字符串 |
void serialPrintf (int fd, char *message, ...) | 串口打印,用法跟printf一样 |
int serialDataAvail (int fd) | 返回串口接收缓存区的可用字节数 |
int serialGetchar (int fd) | 从接收缓存区得到一个字节 |
Git例程源码仓库:https://github.com/ZhiliangMa/raspberry.git
(从串口接收缓存区读取10个字节,并完整输出接收到的数据)
#include
#include
#include
int main(void)
{
int hs1;
int snum = 0;
wiringPiSetup(); // 使用wiring编码去初始化GPIO序号
hs1 = serialOpen("/dev/ttyS0", 115200); // 打开 /dev/ttyS0 串口设备,波特率115200
printf("ttyS0 uart test1:\n"); // 终端打印
serialPrintf(hs1, "Hello World!\r\n"); // 串口打印
serialPrintf(hs1, "Enter 10 letters:\r\n");
/* 串口缓存区读取10个字节,并完整输出接收到的数据 */
do{
snum = serialDataAvail(hs1); // 获取串口接收缓存区的可用字节数
}while(snum < 10);
while(snum--)
{
serialPutchar(hs1,serialGetchar(hs1)); // 通过串口发送字节
}
serialPrintf(hs1, "\r\nserial close\r\n\r\n"); // 串口打印
serialClose(hs1); // 关闭串口
return 0;
}
(讲串口接收缓存区的内容记录到数组,遇到\n结束,并完整输出接收到的数据)
#include
#include
#include
int main(void)
{
int hs1;
int snum = 0;
int tnum = 0;
unsigned char chrtmp[100];
wiringPiSetup(); // 使用wiring编码去初始化GPIO序号
hs1 = serialOpen("/dev/ttyS0", 115200); // 打开 /dev/ttyS0 串口设备,波特率115200
printf("ttyS0 uart test2:\n"); // 终端打印
serialPrintf(hs1, "Hello World!\r\n"); // 串口打印
serialPrintf(hs1, "Enter a paragraph and end with Enter:\r\n");
/* 串口缓存区记录到数组,遇到\n结束,并完整输出接收到的数据 */
while (1)
{
snum = serialDataAvail(hs1); // 获取串口接收缓存区的可用字节数
if(snum > 0)
{
chrtmp[tnum] = serialGetchar(hs1); // 从接收缓存区读取一个字节
tnum ++;
if(chrtmp[tnum - 1] == '\n') break;
}
//delay(2000);
//printf("%d , %d\n",snum,tnum);
}
int i = 0;
while (tnum--)
{
serialPutchar(hs1,chrtmp[i++]); // 通过串口发送字节
}
serialPrintf(hs1, "\r\nserial close\r\n\r\n"); // 串口打印
serialClose(hs1); // 关闭串口
return 0;
}
从 wiringSerial.c 中截取的一段代码,里面定义了波特率的设置,串口波特率只能选择其中的值使用。
switch (baud)
{
case 50: myBaud = B50 ; break ;
case 75: myBaud = B75 ; break ;
case 110: myBaud = B110 ; break ;
case 134: myBaud = B134 ; break ;
case 150: myBaud = B150 ; break ;
case 200: myBaud = B200 ; break ;
case 300: myBaud = B300 ; break ;
case 600: myBaud = B600 ; break ;
case 1200: myBaud = B1200 ; break ;
case 1800: myBaud = B1800 ; break ;
case 2400: myBaud = B2400 ; break ;
case 4800: myBaud = B4800 ; break ;
case 9600: myBaud = B9600 ; break ;
case 19200: myBaud = B19200 ; break ;
case 38400: myBaud = B38400 ; break ;
case 57600: myBaud = B57600 ; break ;
case 115200: myBaud = B115200 ; break ;
case 230400: myBaud = B230400 ; break ;
case 460800: myBaud = B460800 ; break ;
case 500000: myBaud = B500000 ; break ;
case 576000: myBaud = B576000 ; break ;
case 921600: myBaud = B921600 ; break ;
case 1000000: myBaud = B1000000 ; break ;
case 1152000: myBaud = B1152000 ; break ;
case 1500000: myBaud = B1500000 ; break ;
case 2000000: myBaud = B2000000 ; break ;
case 2500000: myBaud = B2500000 ; break ;
case 3000000: myBaud = B3000000 ; break ;
case 3500000: myBaud = B3500000 ; break ;
case 4000000: myBaud = B4000000 ; break ;
default:
return -2 ;
}