历史上的今天
返回首页

历史上的今天

今天是:2024年11月25日(星期一)

正在发生

2020年11月25日 | 从STM32到TM4C123

2020-11-25 来源:eefocus

我主要是最近看ACfly的代码时,发现他有的工程的文件的.s文件讲道理是启动文件不是STM32,而是TM4C123,我怀疑是TI的芯片,查了下果然是的,应该是电赛准备的。但是这里可以看到换成其他芯片也是有专门的启动文件的。

 

 

 

 

从51单片机到STM32再到TM4C123

 

目录

系统时钟

GPIO相关

通用定时器相关

PWM相关

UART通信相关

 

写在前面:

进入TI的学习,说明STM32 已经掌握的差不多了,没有掌握的很好也没关系,正好两块单片机对比着学习更能加深映像。这篇只是简单的介绍TI,篇幅比较短比,主要还是叙述了32和TI的不同的地方,相似的就没有再写出来,不能完全的拿来当作学习资料。

 

一点学习TI的建议:

TI主要学习还是通过北航出版的《嵌入式系统教程——基于TivaC系列 ARM Cortex—M4微控制器》为主资料,因为这个资料比较通俗易懂,如果不喜欢看电子版的,可以去图书馆借这本书,还有一本配套的书,忘记叫啥名字了,但是想借的话直接图书馆检索TM4C123GH6PM就可以找到,这本书主要还是纯文字教你怎么配置相应功能和相应项目的思路。其次,除了北航的那本书,配套的资料还应该有《TM4C1233H6PM数据手册中文版》、中英文版本的《TM4CDriver_Library》,数据手册的话主要就是了解相关外设功能,以及对应映射引脚查找。《TM4CDriver_Library》主要是API文档,因为TI不同于32,TI的函数的入口参数无法通过像32一样的方法查找选择合适的参数,所以,该文档就很有作用,对于一个函数,可以通过该文档进行查找,找到函数所在的位置,有详细的关于该函数的讲解,可以了解该功能,同时还有入口参数的例子,若要选择其他入口参数,则复制该参数,在程序文件里面查找定义的位置,就可以看到附近还有同类的参数,选择需要的参数即可。


对于单片机的定时,那是一部分很重要的东西,这其中就有以分资料单独讲怎么配置各种定时器,实现不同功能,有例程,《TM4C123G定时器》就是一份资料,学习定时器的时候对照着来,会比较容易很多。


当然了,网上还有很多人的学习记录博客,这些也是很有用的资料,因为学习TI,就是要知道怎么用,怎么配置相关程序,博客就解决了这类问题。CSDN上面这一类型的TI教程不多,懒得找的话可以来找我拷贝。


系统时钟

对于51单片机来说,在书写程序时候是不需要进行系统的时钟函数的配置的,直接由晶振电路来提供。

 

如图所示,直接是32和TI的系统时钟框图

32系统时钟

TI系统时钟

 

对于32 的时钟来说,常用的时钟主要分为AHB和APB两大部分,且系统时钟不需要自己来配置。

/*

void RCC_AHB1PeriphClockCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState);
void RCC_AHB2PeriphClockCmd(uint32_t RCC_AHB2Periph, FunctionalState NewState);
void RCC_AHB3PeriphClockCmd(uint32_t RCC_AHB3Periph, FunctionalState NewState);
void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);

*/

每个部分对应多大的频率,对应的定时器编号,串口编号也已经设定好。所以,在使用相对应的功能时候直接在这两类里面进行查找然后使能外设就可以用了,例如使用GPIO、定时器等功能时候直接用函数里面的参数来查找:
/*

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);//使能 GPIOA 时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能串口

*/

 

然而,对于TI来说,系统的时钟也是分为AHB和APB两种,但是在配置时候可进行自由选择(由于初入TI,对这里没有仔细学习,感兴趣的可以了解),但是配置时钟时候,可以只需要运用“SysCtlClockSet()”函数来自己来设定,不像32一样直接规定了不同外设用不同的频率。函数的入口参数就是:系统的分频、使用OSC还是PLL、OSC时钟源选择、外接晶体频率,这四种来完成设备的时钟,例如:

/*

SysCtlClockSet ( SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_XTAL_16MHZ SYSCTL_OSC_MAIN )

*/

最后使能相应的功能即可。(关于其时钟配置的参数详细讲解见)。

在配置好系统的时钟之后,根据需要的外设功能进行相应的使能:

/*

SysCtlPeripheralEnable(uint32_t ui32Peripheral)

*/

其中的入口参数为 SYSCTL_PERIPH_GPIOA 、 SYSCTL_PERIPH_PWM1、 SYSCTL_PERIPH_TIMER1 等等。

注意:32的系统频率的配置是 固定的,定在了不同的总线的使能函数 ,所以不同的外设可以说是“不共用”系统时钟的,而TI是先于外设使能前进行自己 时钟 配置,然后才 使能 所需外设,且“公用”系统时钟。

GPIO相关

说完时钟和系统配置,下面简绍基本的GPIO口的配置。

 

GPIO的功能大致上还是和32的类似,可输出高低电平、UART通信、还可以模拟一些简单的通信接口,如SPI,IIC等。一般工作模式有以下几种:

浮空输入

上拉输入

下拉输入

模拟输入

开漏输出

推挽输出

复用推挽输出

复用开漏输出

 

一般GPIO在复位之后都有一个默认的方向,为了安全起见,都是默认为输入模式,废话不多说,直接进入配置:

首先是32的配置

/*

void LED_Init(void)

{

GPIO_InitTypeDef  GPIO_InitStructure;              

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);            

 

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;                                                      

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                           

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                           

GPIO_Init(GPIOB, &GPIO_InitStructure);                                                                     

GPIO_SetBits(GPIOB,GPIO_Pin_5);            

 

GPIO_Init(GPIOE, &GPIO_InitStructure);                                                                                                                                             

}

*/

其次是TI的配置:

/*

SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);      //使能GPIOF外设         GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE,GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);

*/

 

不难看出,配置32和TI的方式就是不一样的,32的GPIO是用结构体进行配置,TI则使用函数来进行配置。TI的普通配置只需要进行GPIO外设使能和方向控制即可。也不是说前面说到的功能模式就不能配置了,如果有需要可以进行其他类型的配置。

如果要进行端口高低电平的输出控制,32和TI也是一样的调用函数来进行配置,分别是:GPIO_SetBits(GPIOE,GPIO_Pin_5); 和 GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, 0);

 

注意:TI的输出高低电平使用的是同一个函数GPIOPinWrite(),对于32则使用的是两个函数:GPIO_SetBits()和GPIO_ResetBit()即可输出高低电平。TI呢,则不是这样的,就连入口参数也不是和32一样那么简单,GPIOPinWrite()入口参数就有三个,分别是GPIO_PORTx_BASE,GPIO_PIN_x,和0(低电平时候为0,但是高电平时候不是1,而是GPIO_PIN_x)。例如PF1输出高电平 :

GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, GPIO_PIN_1);

 

如果想进行其他端口详细的配置情况可以见相关手册资料,其中端口复用放在后面各功能实现时候讲。

通用定时器相关

TI定时器简介:

TI定时器呢,主要分为12个大的定时器模块(GPTM),每个定时器模块又分为定时器A和定时器B,所以总共有24个定时器。这12个大的定时器的属性分为16/32位的GPTM块和32/64位块,其中各6块。每个16/32位的定时器块,提供2路16位的定时器/计数器(即定时器A和定时器B),所以通俗来说就是定时器A或B单独配置时候就是12个16位的定时器,级联起来配置就是6个32位的定时器。同样的,32/64位的块就是12个32位的定时器,级联时候就变成6个64位的定时器。

功能说明:

每个 GPTM 模块的主要元件包括两个自由运行的递增/递减计数器(称作 Timer A 和 Timer B)、两个预分频器寄存器、两个匹配寄存器、两个预分频器匹配寄存器、两个影子寄存器、两个加载/初始化寄存器以及与它们相关的控制功能。

接着来,该单片机的定时器和32的有点不同,特别是计数控制计数的寄存器。配置了32的定时器之后,定时器开始计数,当计数达到重装载值时候产生中断,之后会重新“自动”装载计数值,但是Ti却并非如此,是否自动装载计数值是需要在配置时候进行设置的,官方一点的来说就是:单次触发 /周期定时器模式。

相关定时器的功能如下:

 

 

接着进入配置对比:

首先还是先32的配置:

/*

              TIM_TimeBaseStructure.TIM_Period = arr;

              TIM_TimeBaseStructure.TIM_Prescaler =psc;

              TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;

              TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

              TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

*/

 

TI的配置:

/*

//TimerConfigure(TIMER0_BASE, TIMER_CFG_ONE_SHOT);//单次计数模式

TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC);//周期性计数模式

TimerLoadSet(TIMER0_BASE, 2222222- 1);//设定预装栽值

IntEnable(INT_TIMER0A);  //使能TIMER0A

TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT); //TIMEOUT标志位触发中断

  //TIMER0A开始计数,当计数值等于TimerLoadSet,触发中断

*/

 

同GPIO口的配置一样的,32的配置还是结构体类型的配置,TI还是调用函数进行配置。

 

 

PWM模式:

通用定时器支持简单的PWM生成模式。在 PWM 模式中,定时器被配置为 24 位或 48 位递减计数器,也就是说在定时器里面就有这个功能,配置好以后就直接输出PWM,而不像32一样配置好定时器之后还要一个TIM_SetCompare1()函数来进行PWM的输出。

 

注意:除了前面介绍的不同点之后,与32还有一个很大的区别就是需要进行中断的执行相关功能时候,需要自己调用TimerIntRegister()函数来注册中断函数的名字,这样中断才有入口。如果不需要忽略即可。同时在使能中断时候,和32一样需要开启一些中断。

 

 

PWM相关

PWM简介:

TI有2个PWM模块,每个模块由4个PWM发生器模块和一个控制器模块组成,一共可以产生16个PWM输出。每个发生器模块都能够产生2个PWM信号,这两个信号是基于同一个定时器和频率,也可以配置成单独产生信号。PWM模块发生器产生的两个信号为PWMA和PWMB。

以下为结构图:

 

功能描述:

  • 时钟选择:系统时钟和预分频系统时钟

  • PWM定时器

每个PWM发生器中都有区别与通用定时器的定时器,在向下计数模式或向上/向下计数模式。

  • PWM比较器

每个PWM发生器都有两个比较器。具体功能和32一样就不再累赘。

  • PWM信号发生器

 

 

初始化及配置:

 

首先还是32的:

/*

              TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;

              TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

              TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

              TIM_OC2Init(TIM3, &TIM_OCInitStructure);

              TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);

*/

 

其次是TI的:
/*

//单独配置的系统时钟

SysCtlPWMClockSet(SYSCTL_PWMDIV_1);

SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1);

//配置引脚为PWM功能

syslPeripheralEnable(SYSCTL_PERIPH_GPIOF);

GPIOPinConfigure(GPIO_PF3_M1PWM7);

GPIOPinTypePWM(GPIOF, Pin3);

//配置 PWM1 Generator3·发生器

PMGenConfigure(PWM1_BASE, PWM_GEN_3, PWM_GEN_MODE_UP_DOWN|PWM_GEN_MODE_NO_SYNC);

//配置 PWM1 Generator3 周期

PWenPeriodSet(PWM1_BASE, PWM_GEN_3, SysCtlClockGet()/freq - 1);

//配置 PWM1 Generator3·占空比

PMPulseWidthSet(PWM1_BASE, PWM_OUT_7, PWMGenPeriodGet(PWM1_BASE, PWM_GEN_3)*duty - 1);

//使能PWM1的输出

PWOutputState(PWM1_BASE, PWM_OUT_7_BIT, true);

//使能 PWM1 发生器模块

PMGenEnable(PWM1_BASE, PWM_GEN_3);

*/

 

还是和前面一样,32的PWM配置过程是结构体类型的,而TI则还是库函数来进行配置的。有一点值得注意哦,TI在配置PWM时候不需要进行IO口的复用配置和映射等相关操作,只要找到对应的IO口就可以输出信号。

 

UART通信相关

微控制器的UART简介:

TI控制器配备了多达8路的UART,其基本功能和32差不多,具体功能可以参考32相关文档

 

 

这部分我们先来看32和TI的配置,从配置中找不同的地方加以说明

 

首先是32配置:

/*

USART_InitStruct.USART_BaudRate=arr;

USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None;

USART_InitStruct.USART_Mode=USART_Mode_Tx | USART_Mode_Rx;

USART_InitStruct.USART_Parity=USART_Parity_No;

USART_InitStruct.USART_StopBits= USART_StopBits_1;

USART_InitStruct.USART_WordLength= USART_WordLength_8b;

USART_Init(USART2, &USART_InitStruct);

 

              USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);

              USART_Cmd(USART2, ENABLE);

*/

32的配置过程就不加以叙述

 

TI的配置:

/*

    SCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);              //使能GPIO

              SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);//使能UART0

              GPIOPinConfigure(GPIO_PA0_U0RX); //复用GPIO

              GPIOPinConfigure(GPIO_PA1_U0TX);·

              GPIOPinTypeUART(GPIO_PORTA_BASE,GPIO_PIN_0|GPIO_PIN_1);//

推荐阅读

史海拾趣

Compact公司的发展小趣事

随着全球环保意识的提高,电子行业对环保和可持续发展的要求也越来越高。Compact公司积极响应这一趋势,加大环保投入,采用环保材料和工艺,降低生产过程中的能耗和排放。同时,公司还致力于推动循环经济的发展,通过回收和再利用废旧电子产品,减少资源浪费和环境污染。这一举措不仅提升了公司的社会形象,还为公司的可持续发展奠定了坚实基础。

请注意,以上故事仅为示例,并不代表任何真实存在的企业情况。如果需要关于特定企业(如Compact公司)的准确信息,建议查阅相关公司的官方资料、行业报告或新闻报道。

Delus Corp公司的发展小趣事

Delus Corp公司非常重视人才培养和团队建设。公司积极引进高素质人才,并为员工提供良好的培训和发展机会。公司建立了完善的激励机制和绩效考核体系,激发员工的工作积极性和创造力。同时,公司还注重团队建设和文化建设,营造了一个积极向上、团结协作的工作氛围。这些措施的实施,使得公司拥有一支高素质、专业化的团队,为公司的发展提供了有力的人才保障。

ECM [ECM Electronics Limited.]公司的发展小趣事

随着公司规模的扩大和产品线的丰富,ECM Electronics Limited.开始积极拓展市场。公司不仅在国内市场取得了良好的销售业绩,还积极开拓国际市场,将产品出口到多个国家和地区。为了更好地服务全球客户,公司还设立了海外办事处和研发中心,加强与国际市场的联系和合作。通过国际化战略的实施,ECM进一步提升了品牌知名度和市场竞争力。

AiT Semiconductor Inc公司的发展小趣事

在半导体行业,技术创新是企业持续发展的关键。AiT公司深知这一点,因此始终将创新作为公司的核心竞争力。他们投入大量资金和资源用于研发,不断推出具有创新性和领先性的半导体产品。同时,公司还积极与高校、科研机构等合作,共同开展技术研发和人才培养工作。这些创新举措使得AiT公司在行业中始终保持领先地位。

FERYSTER公司的发展小趣事

随着市场的不断扩大,FERYSTER公司意识到产品质量对于企业的重要性。因此,公司投入大量资金用于提升质量管理体系,引入国际先进的生产设备和检测仪器。同时,公司还加强了员工的质量意识培训,确保每一个环节都符合质量标准。这些措施的实施,使得FERYSTER公司的产品质量得到了显著提升,赢得了客户的广泛赞誉。

宝乘(baocheng)公司的发展小趣事

在激烈的市场竞争中,宝乘公司始终坚持质量为本的原则。公司建立了严格的质量管理体系,从原材料采购到生产加工、产品测试等各个环节都严格把关。正是这种对质量的执着追求,让宝乘的产品赢得了客户的信赖和好评。许多知名企业都成为了宝乘的长期合作伙伴,共同推动电子行业的发展。

问答坊 | AI 解惑

200元做个实物,对高手来说毫无难道,呵呵

我做的是球赛计时计分器,要求如下: 本系统通过单片机AT89C51芯片来控制LED七段数码管和矩阵作时间、分数、队名称显示的球赛计时计分系统。本系统具有赛程定时设置、赛程时间暂停、球赛种类的切换、及时刷新甲、乙队双方的成绩以及赛后成绩暂存等 ...…

查看全部问答>

$(_COMMONOAKROOT)\lib\$(_CPUINDPATH)\LayoutManager.lib \这个是什么意思 ?

$(_COMMONOAKROOT)\\lib\\$(_CPUINDPATH)\\LayoutManager.lib \\这个路径在sources文件中用到了 对应的实际路径是C:\\WINCE600\\PUBLIC\\COMMON\\OAK\\LIB\\ARMV4I\\RETAIL。也就是说 $(_COMMONOAKROOT)对应C:\\WINCE600\\PUBLIC\\COMMON\\OAK\\ ...…

查看全部问答>

如何在控制面板加上一个背光控制的高级选项?

ADVBACKLIGHT,这个文件源代码是用在控制面板里的,请问怎么样可以使控制面板的背光设置里有一个高级选项?因为默认是没有的!…

查看全部问答>

简单winCE例程开发,有偿。有愿意做的朋友进

本人现需几个winCE的示例程序,要求EVC4.0开发,内容涉及绘图、文字显示、串口通讯以及打印几个方面,运行环境WinCE,CPU ARM4/ARM41。 若有掌握相关技术的朋友感兴趣,请加QQ:575336,工作日白天9:00-17:00在线。 开发周期及费用详谈。…

查看全部问答>

中文字库数组过大的问题!!!有人提过,但解决是小数组的问题!

每个中文字体结构体定义 typedef struct typFNT_GB16        {        unsigned char index[2];        // 汉字内码索引        unsigned char dot_data[32 ...…

查看全部问答>

哪位大虾有比较好的KEIL或C51的视频教程呀?

哪位大虾有比较好的KEIL,C51视频教程呀,请把网址告诉小弟。万分感激。。。。 帮小弟顶下也有分噢!!…

查看全部问答>

我是该版块的新人,有几个基础的问题想请各位前辈指点指点,顶者有分

我的基本情况 1> 对 Visual studio 2003/2005 中vb.net c#.net 相对熟悉    (因为开发过.Net 的项目所以数据也还算熟悉) 2> 熟悉 JSDK2.0 DOS下的java 开发, 也用JBuilder 8.0以下版本开发一些东西,因此对JAVA 算是有一定的基础 ...…

查看全部问答>

关于stm32和spc3连接的问题

版主,spc和stm32连接时nadv到AlE是不是要接个反相器啊 …

查看全部问答>

stm8s输出比较已——反复思考

以下是输出比较的一段程序,麻烦各位高手看看哪里出错了! #include <STM8S105C_S.h> //unsigned int a; void GPIO_Init(void) { PB_DDR=0XFF; PB_CR1=0XFF; PB_CR2=0XFF; } void clock_init(void) { // CLK_ECKR&=0XFE;//关 ...…

查看全部问答>

我终于回来了,不容易啊

本帖最后由 paulhyde 于 2014-9-15 09:27 编辑 前段时间骨折了,做了个手术,现在还在恢复,不方便上网,一直没来坛子,电子大赛也放下了,考研也落下了,辛昕的活动也没参加完,不好意思啊,现在终于可以稍微活动了,唉,还是正常人好,以后要好 ...…

查看全部问答>