实验八--uart

一。环境

  系统:ubuntu12.04

  开发板:jz2440

  编译器:gcc

二。说明

    有空补上

三。代码

      head.S

 1 @******************************************************************************

 2 @ File:head.S

 3 @ 功能:设置SDRAM,将程序复制到SDRAM,然后跳到SDRAM继续执行

 4 @******************************************************************************       

 5    

 6 .extern     main

 7 .text 

 8 .global _start 

 9 _start:

10 Reset:                  

11     ldr sp, =4096           @ 设置栈指针,以下都是C函数,调用前需要设好栈

12     bl  disable_watch_dog   @ 关闭WATCHDOG,否则CPU会不断重启

13     bl  clock_init          @ 设置MPLL,改变FCLK、HCLK、PCLK

14 

15     ldr pc, =on_sdram                   @ 跳到SDRAM中继续执行

16 on_sdram:

17     ldr sp, =0x34000000     @ 设置栈指针

18     ldr lr, =halt_loop      @ 设置返回地址

19     ldr pc, =main           @ 调用main函数

20 halt_loop:

21     b   halt_loop

Makefile

 1 objs := head.o init.o serial.o main.o

 2 

 3 uart.bin: $(objs)

 4     arm-linux-ld -Ttext 0x00000000 -o uart_elf $^

 5     arm-linux-objcopy -O binary -S uart_elf $@

 6     arm-linux-objdump -D -m arm uart_elf > uart.dis

 7     

 8 %.o:%.c

 9     arm-linux-gcc -Wall -O2 -c -o $@ $<

10 

11 %.o:%.S

12     arm-linux-gcc -Wall -O2 -c -o $@ $<

13 

14 clean:

15     rm -f uart.bin uart_elf uart.dis *.o        

16     

init.c

 1 /*

 2  * init.c: 进行一些初始化

 3  */ 

 4 

 5 #include "s3c24xx.h"

 6  

 7 void disable_watch_dog(void);

 8 void clock_init(void);

 9 

10 

11 /*

12  * 关闭WATCHDOG,否则CPU会不断重启

13  */

14 void disable_watch_dog(void)

15 {

16     WTCON = 0;  // 关闭WATCHDOG很简单,往这个寄存器写0即可

17 }

18 

19 #define S3C2410_MPLL_200MHZ     ((0x5c<<12)|(0x04<<4)|(0x00))

20 #define S3C2440_MPLL_200MHZ     ((0x5c<<12)|(0x01<<4)|(0x02))

21 /*

22  * 对于MPLLCON寄存器,[19:12]为MDIV,[9:4]为PDIV,[1:0]为SDIV

23  * 有如下计算公式:

24  *  S3C2410: MPLL(FCLK) = (m * Fin)/(p * 2^s)

25  *  S3C2410: MPLL(FCLK) = (2 * m * Fin)/(p * 2^s)

26  *  其中: m = MDIV + 8, p = PDIV + 2, s = SDIV

27  * 对于本开发板,Fin = 12MHz

28  * 设置CLKDIVN,令分频比为:FCLK:HCLK:PCLK=1:2:4,

29  * FCLK=200MHz,HCLK=100MHz,PCLK=50MHz

30  */

31 void clock_init(void)

32 {

33     // LOCKTIME = 0x00ffffff;   // 使用默认值即可

34     CLKDIVN  = 0x03;            // FCLK:HCLK:PCLK=1:2:4, HDIVN=1,PDIVN=1

35 

36     /* 如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode” */

37 __asm__(

38     "mrc    p15, 0, r1, c1, c0, 0\n"        /* 读出控制寄存器 */ 

39     "orr    r1, r1, #0xc0000000\n"          /* 设置为“asynchronous bus mode” */

40     "mcr    p15, 0, r1, c1, c0, 0\n"        /* 写入控制寄存器 */

41     );

42 

43     /* 判断是S3C2410还是S3C2440 */

44     if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))

45     {

46         MPLLCON = S3C2410_MPLL_200MHZ;  /* 现在,FCLK=200MHz,HCLK=100MHz,PCLK=50MHz */

47     }

48     else

49     {

50         MPLLCON = S3C2440_MPLL_200MHZ;  /* 现在,FCLK=200MHz,HCLK=100MHz,PCLK=50MHz */

51     }       

52 }

serial.c

 1 #include "s3c24xx.h"

 2 #include "serial.h"

 3 

 4 #define TXD0READY   (1<<2)

 5 #define RXD0READY   (1)

 6 

 7 #define PCLK            50000000    // init.c中的clock_init函数设置PCLK为50MHz

 8 #define UART_CLK        PCLK        //  UART0的时钟源设为PCLK

 9 #define UART_BAUD_RATE  115200      // 波特率

10 #define UART_BRD        ((UART_CLK  / (UART_BAUD_RATE * 16)) - 1)

11 

12 /*

13  * 初始化UART0

14  * 115200,8N1,无流控

15  */

16 void uart0_init(void)

17 {

18     GPHCON  |= 0xa0;    // GPH2,GPH3用作TXD0,RXD0

19     GPHUP   = 0x0c;     // GPH2,GPH3内部上拉

20 

21     ULCON0  = 0x03;     // 8N1(8个数据位,无较验,1个停止位)

22     UCON0   = 0x05;     // 查询方式,UART时钟源为PCLK

23     UFCON0  = 0x00;     // 不使用FIFO

24     UMCON0  = 0x00;     // 不使用流控

25     UBRDIV0 = UART_BRD; // 波特率为115200

26 }

27 

28 /*

29  * 发送一个字符

30  */

31 void putc(unsigned char c)

32 {

33     /* 等待,直到发送缓冲区中的数据已经全部发送出去 */

34     while (!(UTRSTAT0 & TXD0READY));

35     

36     /* 向UTXH0寄存器中写入数据,UART即自动将它发送出去 */

37     UTXH0 = c;

38 }

39 

40 /*

41  * 接收字符

42  */

43 unsigned char getc(void)

44 {

45     /* 等待,直到接收缓冲区中的有数据 */

46     while (!(UTRSTAT0 & RXD0READY));

47     

48     /* 直接读取URXH0寄存器,即可获得接收到的数据 */

49     return URXH0;

50 }

51 

52 /*

53  * 判断一个字符是否数字

54  */

55 int isDigit(unsigned char c)

56 {

57     if (c >= '0' && c <= '9')

58         return 1;

59     else

60         return 0;       

61 }

62 

63 /*

64  * 判断一个字符是否英文字母

65  */

66 int isLetter(unsigned char c)

67 {

68     if (c >= 'a' && c <= 'z')

69         return 1;

70     else if (c >= 'A' && c <= 'Z')

71         return 1;       

72     else

73         return 0;

74 }

main.c

 1 #include "serial.h"

 2 

 3 int main()

 4 {

 5     unsigned char c;

 6     uart0_init();   // 波特率115200,8N1(8个数据位,无校验位,1个停止位)

 7 

 8     while(1)

 9     {

10         // 从串口接收数据后,判断其是否数字或子母,若是则加1后输出

11         c = getc();

12         if (isDigit(c) || isLetter(c))

13             putc(c+1);

14     }

15 

16     return 0;

17 }

 

 

注:代码源自韦东山先生,简作修改。

删掉sdram部分内容

 

上面代码只是测试串口用,下面贴出实用的串口代码,可以输出打印信息,这点在uboot和内核很有用

而且这里不用硬件重定向

对于上面代码作修改如下

serial.c里面添加:

 1 void puts(unsigned char *str)

 2 {

 3     int i=0;

 4     while(str[i])

 5     {

 6       putc(str[i]);

 7       i++;    

 8     }    

 9 

10 

11 }

当然serial.h里面也相应的删减,去掉对输入字符判断函数

此外,mian函数可以作出一个菜单选项

 1 #include "serial.h"

 2 

 3 int main()

 4 {

 5     unsigned char c;

 6     uart0_init();   // 波特率115200,8N1(8个数据位,无校验位,1个停止位)

 7 

 8     while(1)

 9     {

10         // 从串口接收数据后,判断其是否数字或子母,若是则加1后输出

11         c = getc();

12     switch(c)

13     {

14       case '0':

15         {

16         puts("I\n\r");

17         break;

18         }    

19       case '1':

20         {

21         puts("AM\n\r");

22         break;    

23         }

24       case '2':

25         {

26         puts("HELLO\n\r");

27         break;

28         }    

29       case '3':        

30         {

31         puts("WORLD\n\r");

32         break;    

33         }

34       default:

35         {

36         puts("thanks!\n\r");

37         break;    

38         }

39     }

40     }

41 

42     return 0;

43 }

输出会相对输入作出不同响应,在后面做菜单方面很有用。

韦东山老师用作菜单的串口函数是硬件重定向,没这个简练

 

经测试,可用。

 

你可能感兴趣的:(r)