实验八--uart

发布时间:2023-06-09  

一。环境


  系统: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, 0n"        /* 读出控制寄存器 */ 

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

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

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("Inr");

17         break;

18         }    

19       case '1':

20         {

21         puts("AMnr");

22         break;    

23         }

24       case '2':

25         {

26         puts("HELLOnr");

27         break;

28         }    

29       case '3':        

30         {

31         puts("WORLDnr");

32         break;    

33         }

34       default:

35         {

36         puts("thanks!nr");

37         break;    

38         }

39     }

40     }

41 

42     return 0;

43 }


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


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


 


经测试,可用。


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

相关文章

    中国量子卫星在轨测试顺利:11月正式交付;据中科院透露,全球第一颗量子科学实验卫星“墨子号”正在进行为期三个月的在轨测试,目前状态良好。 预计到11月中旬,墨子号将完成全部在轨测试工作,随后......
    技术为核心的全体系量子教学解决方案,助力相关专业与课程的建设。 九章量子教学解决方案提供从实验室建设到教学实验仪器、配套软件、讲义、课件、师资培训的全方位服务。实验内容丰富,涵盖从量子基础实验到量子信息科学专业实验......
    是中国目前为止持续时间最长的太空飞行。 “神舟十一号”目前已进入轨道,预计 2 天内将与上月才发射升空的太空实验室“天宫二号”对接形成组合体,在太空进行太空医学实验与科学实验、在轨维修与科普活动等,并借宇航员这次为期 33 天的......
    是中国目前为止持续时间最长的太空飞行。 “神舟十一号”目前已进入轨道,预计 2 天内将与上月才发射升空的太空实验室“天宫二号”对接形成组合体,在太空进行太空医学实验与科学实验、在轨维修与科普活动等,并借宇航员这次为期 33 天的......
    分,在中国甘肃酒泉卫星发射中心,长征二号丁运载火箭成功将一颗卫星发射升空,然而,这颗卫星与目前所发射过的大多数卫星大不相同,它是全球第一颗量子科学实验卫星——名为“墨子号”,升空......
    分,在中国甘肃酒泉卫星发射中心,长征二号丁运载火箭成功将一颗卫星发射升空,然而,这颗卫星与目前所发射过的大多数卫星大不相同,它是全球第一颗量子科学实验卫星——名为“墨子号”,升空......
    完成与天宫二号的自动交会对接,形成组合体,航天员进驻天宫二号,组合体在轨飞行30天。这也将是中国史上时间最长的太空驻留飞行任务。 期间,2名航天员将按照飞行手册、操作指南和地面指令进行工作和生活,按计划开展有关科学实验......
    效率,降低试错成本。我十分看好智化技术在新材料研发中发挥的作用,相信我们的合作将进一步推动科学研究智动化的发展,并继续拓展智化技术的应用空间。” 智化科技的化学实验......
    中国科学家在空间站完成铟硒半导体晶体生长实验;据科技日报报道,从中国科学院空间应用工程与技术中心获悉,利用中国空间站高温材料科学实验柜,我国科研人员完成铟硒半导体晶体生长实验,获得......
    科技)精心策划,旨在激发学生对科学的热爱,为孩子们的未来插上科技的翅膀。 据了解,今年早些时候,深圳科技通过广东省教育基金会向捐赠了一批电脑,为孩子们提供了更好的学习条件。此次活动正值来临之际,深圳......

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>