历史上的今天
返回首页

历史上的今天

今天是:2025年10月28日(星期二)

正在发生

2022年10月28日 | 【JZ2440笔记】串口通信(中断方式)

2022-10-28 来源:csdn

一、前言

本文是在上一篇文章《【JZ2440笔记】串口通信》的基础上写的,上一篇使用的是查询的方式,这一篇使用中断的方式,具体的串口介绍和配置就不写了,都在上一篇了,关于中断方面的设置在《【JZ2440笔记】裸机实验使用中断》中有讲到,这里直接贴出本文代码。


二、程序编写

程序分为以下几个文件:


head.S;启动文件。


init.c:关闭看门狗,初始化时钟的函数。


uart.c:串口相关配置。


uart.h:串口头文件。


main.c:主函数。


Makefile:编译程序。


每个文件具体内容如下:


head.S


@*************************************************************************

@ File:head.S

@ 功能:设置FCLK到400MHz,然后初始化串口

@*************************************************************************       

.text

.global _start

_start:

@******************************************************************************       

@ 中断向量,本程序中,除Reset和HandleIRQ外,其它异常都没有使用

@******************************************************************************       

    b   Reset

@ 0x04: 未定义指令中止模式的向量地址

HandleUndef:

    b   HandleUndef 

 

@ 0x08: 管理模式的向量地址,通过SWI指令进入此模式

HandleSWI:

    b   HandleSWI

@ 0x0c: 指令预取终止导致的异常的向量地址

HandlePrefetchAbort:

    b   HandlePrefetchAbort

@ 0x10: 数据访问终止导致的异常的向量地址

HandleDataAbort:

    b   HandleDataAbort

@ 0x14: 保留

HandleNotUsed:

    b   HandleNotUsed

@ 0x18: 中断模式的向量地址

    b   HandleIRQ

@ 0x1c: 快中断模式的向量地址

HandleFIQ:

    b   HandleFIQ

    

Reset: 

ldr sp, =4096                       @设置堆栈,因为要调用C语言函数 

bl disable_watch_dog               @关WATCH DOG

bl init_system_clk                 @初始化系统时钟,FCLK=400MHz,HCLK=100MHz,PCLK=50MHz

    msr cpsr_c, #0xd2       @ 进入中断模式

    ldr sp, =3072           @ 设置中断模式栈指针

    msr cpsr_c, #0xd3       @ 进入管理模式

    ldr sp, =4096           @ 设置管理模式栈指针,

                            @ 其实复位之后,CPU就处于管理模式,

                            @ 前面的“ldr sp, =4096”完成同样的功能,此句可省略

msr cpsr_c, #0x53       @ 设置I-bit=0,开IRQ中断

    bl main                            @跳转执行main函数

halt_loop:

    b       halt_loop

 

HandleIRQ:

    sub lr, lr, #4                  @ 计算返回地址

    stmdb   sp!,    { r0-r12,lr }   @ 保存使用到的寄存器

                                    @ 注意,此时的sp是中断模式的sp

                                    @ 初始值是上面设置的3072

    

    ldr lr, =int_return             @ 设置调用ISR即EINT_Handle函数后的返回地址  

    ldr pc, =UART0_Handle            @ 调用中断服务函数

int_return:

    ldmia   sp!,    { r0-r12,pc }^  @ 中断返回, ^表示将spsr的值复制到cpsr


init.c


 

 

/* WOTCH DOG register */

#define REG_WTCON               (*(volatile unsigned long *)0x53000000)

 

/* Sys Clk Config */

#define REG_CLKDIVN             (*(volatile unsigned long *)0x4C000014)

#define REG_CAMDIVN             (*(volatile unsigned long *)0x4C000018)

#define REG_MPLLCON             (*(volatile unsigned long *)0x4C000004)

 

void disable_watch_dog();

void init_system_clk();

 

/*上电后,WATCH DOG默认是开着的,要把它关掉 */

void disable_watch_dog()

{

REG_WTCON = 0;

}

 

void init_system_clk()

{

    //HCLK = FCLK/4, 当 CAMDIVN[9] = 0 时

    //PCLK 设置为 HCLK/2 

    //完成配置FCLK : HCLK : PCLK = 1 : 1/4 : 1/8,DIVN_UPLL是USB的时钟不用管

    REG_CLKDIVN = (2 << 1) | (1 << 0);

 

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

__asm__(

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

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

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

    );

 

    //m=MDIV+8, p=PDIV+2, s=SDIV, Mpll = ( 2 × m × Fin ) / ( p × 2^s )

    //FCLK = (2 * (92 + 8) * 12000000) / ((1 + 2) * 2) = 400000000 = 400MHz

    //配置完MPLL后时钟停振,CPU停止运行等待时钟输出稳定,之后FCLK=400MHz,HCLK=100MHz,PCLK=50MHz */

    REG_MPLLCON = (92<<12)|(1<<4)|(1<<0);

}


uart.c


#include "uart.h"

 

void init_uart(DWORD buadrate)

{

    //Step1,配置GPIO,GPH3(RXD0),GPH2(TXD0)

    //清除相关配置位

    REG_GPHCON &= ~((DWORD)(3 << (2*3)) | (3 << (2*2)));

    REG_GPHDAT &= ~((DWORD)(1 << 3) | (1 << 2));

    REG_GPHUP &= ~((DWORD)(1 << 3) | (1 << 2));

    //设置相关配置位

    REG_GPHCON |= ((DWORD)2 << (2*3)) | (2 << (2*2));

    REG_GPHDAT |= ((DWORD)1 << 3) | (1 << 2);

    REG_GPHUP |= ((DWORD)1 << 3) | (1 << 2);

 

    //无校验,1个停止位,8个数据位

    REG_ULCON0 = 0x03;

    //发送和接受设置为查询/中断模式

    REG_UCON0 = 0x05;

    // REG_UCON0 |= 1 << 5;  //环回模式

    //不使用FIFO

    REG_UFCON0 = 0;

    //不使用流控

    REG_UMCON0 = 0;

 

    //UBRDIVn = (int)( UART clock / ( buad rate x 16) ) –1

    REG_UBRDIV0 = (PCLK_SPEED / (115200 * 16)) - 1;

 

    //中断配置

    REG_INTMSK &= ~((DWORD)1 << 28);    //开UART0中断

    REG_INTSUBMSK &= ~((DWORD)1 << 0);    //开RXT0中断

}

 

void uart_send(BYTE ch)

{

    while(!(REG_UTRSTAT0 & (1 << 2)))

    {

        ;

    }

 

    REG_UTXH0 = ch;

}

 

BYTE uart_receive()

{

    while(!(REG_UTRSTAT0 & (1 << 0)))

    {

        ;

    }

 

    return REG_URXH0;

}

 

void uart_sendString(BYTE *str)

{

    while(*str != '')

    {

        uart_send(*str);

        str++;

    }

}


uart.h


#ifndef _UART_H_

#define _UART_H_

 

#define BYTE unsigned char

#define WORD unsigned short

#define DWORD unsigned int

 

/* Uart Config */

#define PCLK_SPEED              50000000

 

#define REG_GPHCON              (*(volatile unsigned long *)0x56000070)

#define REG_GPHDAT              (*(volatile unsigned long *)0x56000074)

#define REG_GPHUP               (*(volatile unsigned long *)0x56000078)

 

#define REG_ULCON0              (*(volatile unsigned long *)0x50000000)

#define REG_UCON0               (*(volatile unsigned long *)0x50000004)

#define REG_UFCON0              (*(volatile unsigned long *)0x50000008)

#define REG_UMCON0              (*(volatile unsigned long *)0x5000000C)

 

#define REG_UTXH0               (*(volatile unsigned long *)0x50000020)

#define REG_URXH0               (*(volatile unsigned long *)0x50000024)

 

#define REG_UBRDIV0             (*(volatile unsigned long *)0x50000028)

 

#define REG_UTRSTAT0            (*(volatile unsigned long *)0x50000010)

 

#define REG_INTMSK         (*(volatile unsigned long *)0X4A000008)

#define REG_INTOFFSET         (*(volatile unsigned long *)0x4A000014)

 

#define REG_INTSUBMSK (*(volatile unsigned long *)0X4A00001C)

#define REG_SUBSRCPND (*(volatile unsigned long *)0X4A000018)

 

#define REG_SRCPND (*(volatile unsigned long *)0X4A000000)

#define REG_INTPND (*(volatile unsigned long *)0X4A000010)

 

void init_uart(DWORD buadrate);

void uart_send(BYTE ch);

BYTE uart_receive();

void uart_sendString(BYTE *str);

 

#endif


main.c


#include "uart.h"

 

int main()

{

init_uart(115200);

 

while(1)

{

;

}

return 0;

 

void UART0_Handle()

{

uart_send(REG_URXH0);

 

//清中断

REG_SUBSRCPND |= (1 << 0);

REG_SRCPND |= (DWORD)1 << REG_INTOFFSET;

REG_INTPND |= (DWORD)1 << REG_INTOFFSET;

}

 


Makefile


objs := head.o init.o uart.o main.o

 

uart.bin: $(objs)

 

arm-linux-ld -Ttext 0x0000000 -g -o uart_elf $^

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

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

%.o:%.c

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

 

%.o:%.S

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

 

clean:

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

推荐阅读

史海拾趣

Eclipse Magnetics公司的发展小趣事

由于篇幅限制,无法在此处直接提供5个完整的、每篇至少500字的Eclipse Magnetics公司电子行业发展的相关故事。不过,我可以概括地描述几个可能的故事线索,这些线索可以基于Eclipse Magnetics公司的历史、技术发展和市场应用来构建。

  1. 品牌初创与磁铁技术的突破

在1930年代,Eclipse Magnetics的名字首次出现,标志着这个品牌的诞生。随着技术的不断发展,公司在1940年代成为独立公司,并开始专注于磁铁技术的研发。到了1950年代,Eclipse Magnetics在技术上取得了重大突破,他们将磁铁涂上红色,并设计了与公司颜色相匹配的马蹄形标志,这一设计不仅提升了品牌形象,也成为了国际通用标记。这一时期的Eclipse Magnetics,以其独特的技术和产品,开始在电子行业中崭露头角。

  1. 航空航天领域的应用与拓展

随着航空航天技术的不断发展,Eclipse Magnetics看到了磁铁技术在该领域的巨大潜力。公司开始投入大量资源,研发适用于航空航天领域的磁性解决方案。通过不断的技术创新和产品优化,Eclipse Magnetics成功地为航空航天领域提供了高性能、高可靠性的磁铁产品,并在这一领域树立了良好的口碑。

  1. 与制药工业的深入合作

除了航空航天领域,Eclipse Magnetics还与制药工业建立了深入的合作关系。在制药过程中,磁铁技术可以用于磁选机,有效地去除原料中的杂质,提高药品的纯度。Eclipse Magnetics根据制药工业的特殊需求,定制了多款磁选机产品,并提供了全面的技术支持和售后服务。通过与制药工业的深入合作,Eclipse Magnetics不仅拓展了市场,也提升了自身的技术实力。

  1. 在汽车制造行业的应用

随着汽车制造业的快速发展,Eclipse Magnetics也看到了磁铁技术在该领域的广阔前景。公司针对汽车制造中的各个环节,研发了多款适用于不同场景的磁性解决方案。例如,在齿轮箱轴制造过程中,Eclipse Magnetics的磁性过滤器可以保持冷却液的清洁,提高生产效率和产品质量。这些解决方案不仅满足了汽车制造业的需求,也进一步巩固了Eclipse Magnetics在电子行业中的地位。

  1. 创新研发与可持续发展

作为一家专注于磁性技术的公司,Eclipse Magnetics始终将创新作为发展的核心动力。公司不断投入研发资源,推动磁铁技术的不断进步。同时,Eclipse Magnetics也关注可持续发展问题,致力于研发环保、高效的磁性产品。通过创新研发和可持续发展战略的实施,Eclipse Magnetics在电子行业中保持了领先地位,并为未来的发展奠定了坚实的基础。

请注意,以上内容仅为故事线索的概括描述,具体的故事细节和数据需要根据Eclipse Magnetics公司的实际情况进行补充和完善。

Cofan Usa Inc公司的发展小趣事

随着产品线的不断丰富和技术实力的提升,Cofan Usa Inc公司开始积极拓展国内外市场。通过与各大电商平台和实体零售商建立合作关系,公司成功将产品推向更广泛的消费者群体。同时,公司注重品牌建设,通过精准的市场定位和有效的营销策略,逐渐树立了独特的品牌形象。

Gould Ami公司的发展小趣事
电源线路短路、断路或电压不稳定等问题,可能导致控制电路无法正常工作。
Elma Electronic Inc公司的发展小趣事

在Covid-19疫情期间,Elma展现了其应对挑战的能力。公司引入了良好的保护措施,并不断调整和改进以适应疫情带来的变化。同时,Elma还积极响应市场需求,为医疗领域提供了大量旋转开关等关键设备,为欧洲和东南亚的医院做出了重大贡献。此外,公司还为瑞士的客户开发和制造了消毒设备,帮助当地进行疫情防控。

以上5个故事涵盖了Elma Electronic Inc公司在电子行业发展的多个方面,展现了其强大的实力和应对挑战的能力。

C-MEDIA公司的发展小趣事

在音频处理和网络游戏领域取得成功后,C-MEDIA公司并未止步。它持续投入研发资源,不断推动技术创新和产品升级。公司的研发团队致力于开发更高效、更稳定的音频处理芯片,以满足市场对于高品质音频体验的需求。同时,在网络游戏领域,C-MEDIA也不断推出新的游戏内容和服务,以吸引和留住用户。

AKM [Asahi Kasei Microsystems]公司的发展小趣事

随着公司业务的不断扩展,C-MEDIA开始实施全球化战略,积极寻求与国际知名企业的合作。通过与全球领先的电子企业、内容提供商和媒体平台建立战略合作关系,C-MEDIA成功地将自己的技术和产品推向了更广阔的市场。这些合作不仅提升了公司的品牌知名度和市场份额,也为公司的长期发展奠定了坚实的基础。

以上只是C-MEDIA公司在电子行业中的一些重要发展节点和故事的概括性描述。实际上,公司的发展过程中还涉及到许多其他的细节和因素,包括市场竞争、技术创新、人才引进等等。这些故事共同构成了C-MEDIA在电子行业中的发展轨迹,展示了其不断进取、追求卓越的精神风貌。

问答坊 | AI 解惑

重新学习单片机

我在学校没有好好学习,现在有一家公司通知我去面试MCU软件工程师,我心里一点把握都没有怎么办啊?我很想得到这份工作,该怎么临时抱佛脚呢?…

查看全部问答>

DSP算法大全C语言版本

DSP算法大全C语言版本…

查看全部问答>

CPU风扇,本的外置散热风扇是直流的么?51单片机可以控制其转速么?

CPU风扇,本的外置散热风扇是直流的么?51单片机可以控制其转速么? 要怎么搞?…

查看全部问答>

EEW-DSO-V2.00设计思路

这段时间一直和网友东哥在讨论第二版的设计,大概确定了一下,下个版本的设计方案,采样芯片应该会换成ADC08100,最高100M采样,用两片IS61LV25616-10+CPLD来做FIFO,两片轮流寸,实现100M的读写速度.存储深度比上次用了很大的升级,CPU换成带外部总线的STM ...…

查看全部问答>

USB 2.0 规范

USB 2.0 规范 USB 是一种支持热插拔的高速串行传输总线,它使用差分信号来传输数据,最高速度 可达480Mb/S。USB 支持“总线供电”和“自供电”两种供电模式。在总线供电模式下, 设备最多可以获得500mA 的电流。USB2.0 被设计成为向下兼容的模式 ...…

查看全部问答>

请各位分析这样跳槽可以吗?

目前在公司担任研发主管,负责研发部门资源团队,个人觉的资源团队搞起来没啥意思,而且本人在资源团队搞了10年了。现在想需求更大发展。准备跳槽到另一家民营公司担任研发中心下一个研发一部担任部长,负责整个研发部门的工作。我想这样对这样生涯 ...…

查看全部问答>

请问tilt wheel mouse中的WM_MOUSEHWHEEL消息如何在Win200/XP DDK中实现呀?

在Vista中,有mouse消息WM_MOUSEHWHEEL,而在2000/XP中则没有,我想写个mousefilter在2000/XP下来支持该功能,我该如何做呢?在MouseServiceCallback()当中做吗?我看在MOUSE_INPUT_DATA结构中不知怎样才能实现.…

查看全部问答>

酬金500元,北京,请教51单片机的TCP/IP问题

本人在北京,现有一块杭州晶控电子的51NET以太网开发板,开发板介绍:http://www.hificat.com/net/net.asp,想请教一下附带光盘里的单片机源码,(源码已上传,在附件里)。 内容:讲解源码,源码我没仔细看过,是单片机和PC通信的内容,应该是TCP ...…

查看全部问答>

变频器已运行就产生很大的干扰

我是做工控软件的,最近遇到一个让人恼火的问题,我们设备上采用了台安的变频器,我在用串口调试器调试通信时,当变频器运行起来时,一打开串口就有大量的乱码传过来,很是痛苦!!! 什么接地、加电容都试了,,没有解决,,请问各位达人有何高招 ...…

查看全部问答>