在线问答
直播中

杨永胜

11年用户 2379经验值
擅长:嵌入式技术
私信 关注

【OK210试用体验】+第十一篇☞初步尝试(UART字符型)驱动,遇到一些问题,急需解答

本帖最后由 iysheng 于 2015-9-13 15:26 编辑

事情隔了这么久,还要从上次的那个路由器说起,上次的我退货了,然后又重新买了个新的路由器。中间耽搁了一会,但是这个UART程序真的太难了,,我真的的是饱受折磨了,,现在依然有问题还没有解决。首先我说出我的问题,谁要是知道是什么原因了,希望可以解答啊,,,,,,,,
  • 第一个版本,我是自己按照字符驱动的框架,自己写了串口驱动,也就是自己定义了open,write,colse,read函数,这个时候的问题是输出还正常,接受的数据总是0x00 0x00 0x00。 ok1.png error1.png 此时,程序在虚拟机显示如下: ERR.PNG
  • 第二个版本,我直接使用板子自己带的驱动程序,直接对他进行open,write,read操作,结果刚开始一直输出0x5e,0x40,,或者就是0x07,,最后我修改了一部分控制的代码
    1. tcgetattr(fd, &uart1);        
    2.         uart1.c_lflag &= ~(ECHO|ECHOE|ISIG|ICANON);
    3.         uart1.c_oflag &= ~OPOST;
    4.         tcsetattr(fd, TCSANOW,&uart1);
    结果,,一直输出0x00,,,, error2.png error3.png 此时程序在虚拟机中显示如下: error31.png
真的是不知道什么原因,最近试着看内核串口驱动的源代码,也做了很多笔记,可是真的感觉源代码。太复杂了,各个结构体和函数指针,,,真心快崩溃了。附上我自己定义的基于字符型设备的串口驱动源代码:

  1. #include
  2. #include
  3. #include
  4. #include
  5. #include
  6. #include
  7. #include "uart.h"

  8. unsigned int *ulcon3;
  9. unsigned int *ucon3;
  10. unsigned int *ubrdiv3;
  11. unsigned int *udivslot3;
  12. unsigned int *utxh3;
  13. unsigned int *urxh3;
  14. unsigned int *utrstat3;
  15. unsigned int *gpa1con;
  16. unsigned int *gpa1dat;
  17. unsigned int *gpa0con;

  18. struct cdev uartdev;//定义结构体
  19. dev_t devnum;//定义设备号

  20. /*定义open函数*/
  21. int uart_open (struct inode *inode, struct file *filp)
  22. {
  23.         gpa1con = ioremap(GPA1CON, 4);
  24.         writel(0x2200, gpa1con);//设定引脚模式
  25.         
  26.         gpa0con = ioremap(GPA0CON, 4);
  27.         writel(0x22222222, gpa0con);

  28.         ulcon3 = ioremap(ULCON3, 4);
  29.         writel(0x3, ulcon3);//8bit数据
  30.         
  31.         ucon3 = ioremap(UCON3, 4);
  32.         writel(0x5, ucon3);//中断或者查询方式
  33.         
  34.         ubrdiv3 = ioremap(UBRDIV3, 4);
  35.         writel(0x1ac, ubrdiv3);//9600bit,pclk最高66MHZ
  36.         
  37.         udivslot3 = ioremap(UDIVSLOT3, 4);
  38.         writel(0xddd5, udivslot3);//9600bit        
  39.         
  40.         utxh3 = ioremap(UTXH3, 4);
  41.         utrstat3 = ioremap(UTRSTAT3, 4);
  42.         urxh3 = ioremap(URXH3, 4);

  43.         printk(KERN_WARNING"welcome to ysuartn");
  44.         return 0;
  45. }

  46. ssize_t uart_read (struct file *file, char __user *buff, size_t size, loff_t *loft)
  47. {
  48.         unsigned long temp;
  49.         unsigned char temp1;        
  50.         do{
  51.         temp = readl(utrstat3);
  52.         temp &= 0x01;
  53.         }while(!temp);
  54.         temp1 = readb(urxh3);
  55.         temp1 &= 0xff;
  56. writel(temp1, utxh3);
  57. return 0;
  58. }

  59. ssize_t uart_write (struct file *file, const char __user *buff, size_t size, loff_t *loft)
  60. {
  61.         //get_user(*utxh3, buff);
  62.         unsigned int temp;
  63.         do{
  64.         temp = readl(utrstat3);
  65.         temp &= (1<<2);
  66.         }while(!temp);
  67.         copy_from_user(utxh3, buff, size);
  68.         printk(KERN_INFO"num %d has send.",*buff);
  69.         return 0;
  70. }

  71. /*声明函数操作集*/
  72. static struct file_operations uartfops = {
  73.         .open = uart_open,
  74.         .owner = THIS_MODULE,
  75.         .read = uart_read,
  76.         .write = uart_write,
  77. };

  78. static int uart_init(void)//定义驱动入口函数
  79. {
  80.         cdev_init(&uartdev, &uartfops);//联系起来结构体和文件操作集
  81.         alloc_chrdev_region(&devnum, 0, 1, "ysuart");//分配空间
  82.         cdev_add(&uartdev, devnum, 1);//注册驱动
  83.         return 0;
  84. }

  85. static void uart_exit(void)
  86. {
  87.         cdev_del(&uartdev);//删除空间
  88.         unregister_chrdev_region(devnum, 1);//取消注册
  89. }

  90. MODULE_LICENSE("GPL");//声明LICENSE,防止安装时出现警告
  91. MODULE_AUTHOR("SIMON YANG");//声明驱动作者

  92. module_init(uart_init);//声明驱动入口
  93. module_exit(uart_exit);//声明驱动出口
以及使用到的头文件:
  1. #define ULCON3 0XE2900000
  2. #define UCON3 0xE2900004
  3. #define UBRDIV3 0XE2900028
  4. #define UDIVSLOT3 0XE290002C
  5. #define UTXH3 0XE2900020
  6. #define URXH3 0XE2900024
  7. #define UTRSTAT3 0XE2900010

  8. #define GPA0CON 0XE0200000
  9. #define GPA1CON 0XE0200020
  10. #define GPA1DAT 0XE0200024

这个我使用的是UART0(OK210开发板),
自己编写的应用程序:
  1. #include
  2. #include
  3. #include
  4. #include
  5. #include
  6. #include "uart.h"

这是第一种方式,我没有成功,结果是可以正常输入(write函数正常),read函数不行,,,,

然后,我尝试了第二种方法,源代码如下:
  1. #include
  2. #include
  3. #include
  4. #include
  5. #include
  6. #include
  7. #include
  8. #include
  9. #include "uart.h"
  10. #include
  11. //#include //和ioctl函数相关的头文件声明也可以是/sys/ioctl.h

  12. struct termios uart1;


  13. int main(void)
  14. {
  15.         int fd = 0;
  16.         static unsigned char buff[]="hello china";
  17.         unsigned char num = 0;
  18.         int rb;
  19.         int len;
  20.         len = strlen(buff);

  21.         fd = open("/dev/s3c2410_serial1", O_RDWR|O_NOCTTY);//以读写方式打开设备
  22.         if (fd == -1){
  23.                 printf("open the keydev failed! the errno is %dn",errno);
  24.                 return errno;}
  25.                
  26.         tcgetattr(fd, &uart1);        
  27.         uart1.c_lflag &= ~(ECHO|ECHOE|ISIG|ICANON);
  28.         uart1.c_oflag &= ~OPOST;
  29.         tcsetattr(fd, TCSANOW,&uart1);
  30.         
  31.         printf("welcome to linux worldn");
  32.         write(fd, buff, len);
  33.         while(1){        
  34.         rb = read(fd, &num, 1);
  35.         write(fd, &num, 1);
  36.         printf("the number i receive is %dn",num);
  37.         if (rb < 0)
  38.                 perror("read err");
  39.         }
  40.         return 0;
  41. }
这种方法,没有使用我自己编写的驱动程序,最后的结果是,write正常,read还是不行,对回来的数据总是0x00,,,,,
真心寻求问题解答啊,,,,,因为我申请的项目离不开串口啊,,,,
附上一张串口连接的图片(我借用了51开发板上的u***转串口模块):这是第二种方式的照片,用了UART1:
20150909_163842_meitu_1.jpg

已退回10积分

回帖(8)

杨永胜

2015-9-9 23:01:19
本帖最后由 iysheng 于 2015-9-9 23:41 编辑

今天晚上,这个问题解决了,在高手的指点下,我阴差阳错的把这个问题解决了,要想正常的从终端正确显示出来接受到的数据,我犯了如下错误:
1。我使用的是51单片机上的u***转ttl模块,这个模块有问题,不能很好的和ok210通信,这是我犯的知名的错误,导致我一直输出0x00,(其中好像还有一个原因,我选择的波特率不对,要选择9600)。
2。我修改添加的那一部分代码,很重要,那样修改是设置UART,
  1. tcgetattr(fd, &uart1);        
  2.         uart1.c_lflag &= ~(ECHO|ECHOE|ISIG|ICANON);
  3.         uart1.c_oflag &= ~OPOST;
  4.         tcsetattr(fd, TCSANOW,&uart1);

处在原始模式(Raw Mode),来进行通信。
这就是我解决问题的方式,通过上面的修改,今天晚上,我终于解决这个问题,串口操作解决了以后,距离我的项目完成就近了一步,,,加油噢!
下面是我更改后的一些图片,以及实现现象:
换了u***转ttl模块如下:
QQ图片20150909224904.jpg

单个字符接受并直接再通过串口输出
2015-09-09_21-58-28.png

通过串口接受字符串,并在终端上面显示
tesok.png

但是,唯一不完美的是,我自己写的驱动程序,只能通过串口输入输出数据,还是不能正常的在终端上面直接printf回来,这个估计和终端部分的显示(内核层面)有关系了,只是我的猜测,,,,。
在接下来的几天里,我会分别对一下两种方法进行优化:
1。基于我自己的写的驱动程序的操作。
2。基于板子自带的驱动程序。进行编写用户程序,对串口数据进行分析处理。
加油了,,,,
举报

燕小飞

2015-9-10 11:09:28
感觉很高深........楼主威武
举报

杨永胜

2015-9-10 14:24:01
引用: 燕小飞 发表于 2015-9-10 11:09
感觉很高深........楼主威武

{:2:是我自己不细心,,,,
举报

mop

2015-9-17 15:22:14
Read有問題的話,你可能要看看Timing問題,沒對上會讀取到0的data
举报

更多回帖

发帖
×
20
完善资料,
赚取积分