从STM32到TM4C123

2023-05-16

我主要是最近看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_PWM1SYSCTL_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);//
              UARTClockSourceSet(UART0_BASE,UART_CLOCK_PIOSC);//选择串口时钟来源
              UARTStdioConfig(0,115200,16000000);//选择模式、波特率、和时钟大小
*/

 

从配置上可以看出,32和TI的 配置都是需要将UART的端口映射到对应的GPIO口上,当然了,配置过程依旧是32为结构体,TI为调用库函数,但是在配置时候,32还要进行相关NVIC中断配置,设置中断优先级,设置停止位等等。TI的配置就是以上那些函数,其他的功能都是默认,如果需要可以进行自行查找配置。

 

这里还涉及到了端口复用。TI的端口复用很简单,不用像32一样先进行各种IO口的配置,直接用函数SCtlPeripheralEnable() 使能相关IO口的时钟,GPIOPinConfigure() 函数里选择相应复用的功能即可完成配置。
总的来说复用是在你要使用的外设功能函数里面进行的,不需要像32一样拿出来进行配置来使用。
基于UART通信等相关知识点,可以先熟悉32的通信知识点后来使用TI,则会变得容易许多。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从STM32到TM4C123 的相关文章

  • 如何更改闪存的起始地址?

    我正在使用 STM32F746ZG 和 FreeRTOS Flash的起始地址是0x08000000 但我想把它改成0x08040000 我通过谷歌搜索了这个问题 但没有找到解决方案 我更改了链接器脚本 如下所示 MEMORY RAM xr
  • 以字符串形式接收数字(uart)

    我正在尝试通过 uart 接收一个包装为字符串的数字 我发送数字 1000 所以我得到 4 个字节 空字符 但是 当我使用 atoi 将数组转换为数字并将整数与 1000 进行比较时 我并不总是得到正确的数字 这是我用于接收号码的中断处理函
  • CMSIS 库是否应该包含在版本控制中? [复制]

    这个问题在这里已经有答案了 通常 我曾经在版本控制中包含芯片供应商 ST 提供的设备特定标头和源以及 CMSIS Core 标头 数量不多 也没有更新的习惯 我使用STM32微控制器 但我不使用立方体框架 or the 标准外设库 最近 我
  • 140-基于stm32单片机智能晾衣杆控制系统Proteus仿真+源程序

    资料编号 140 一 功能介绍 1 采用stm32单片机 LCD1602显示屏 独立按键 DHT11传感器 ds1302时钟 光敏传感器 蜂鸣器 LED灯 制作一个基于stm32单片机智能晾衣杆控制系统Proteus仿真 2 通过光敏传感器
  • 136-基于stm32单片机家庭温湿度防漏水系统设计Proteus仿真+源程序

    资料编号 136 一 功能介绍 1 采用stm32单片机 LCD1602显示屏 独立按键 DHT11传感器 蜂鸣器 制作一个基于stm32单片机家庭温湿度防漏水系统设计Proteus仿真 2 通过DHT11传感器检测当前温湿度 并且显示到L
  • 135-基于stm32单片机超声波非接触式感应水龙头控制系统Proteus仿真+源程序

    资料编号 135 一 功能介绍 1 采用stm32单片机 LCD1602显示屏 独立按键 DHT11传感器 电机 超声波传感器 制作一个基于stm32单片机超声波非接触式感应水龙头控制系统Proteus仿真 2 通过DHT11传感器检测当前
  • rt-thread studio中新建5.0不能用

    文章目录 一 版本对比 二 文件和文件夹打斜杠 在使用RT Thread studio创建新工程5 0版本的时候 结果发现新建完成之后程序不能正常运行 但是创建4 10版本的时候却能运行 那肯定是新版本出现了BUG 一 版本对比 首先对比了
  • STM32F4 通过软复位跳转到引导加载程序,无需 BOOT0 和 BOOT1 引脚

    我问这个问题是因为可以在这里找到类似问题的答案 通过应用程序跳转到 STM32 中的引导加载程序 即从用户闪存在引导模式下使用引导 0 和引导 1 引脚 用户 JF002 JF002回答 当我想跳转到引导加载程序时 我在其中一个备份寄存器中
  • STM32用一个定时器执行多任务写法

    文章目录 main c include stm32f4xx h uint32 t Power check times 电量检测周期 uint32 t RFID Init Check times RFID检测周期 int main Timer
  • STM32F103

    提示 来源正点原子 参考STM32F103 战舰开发指南V1 3PDF资料 文章目录 前言 一 pandas是什么 二 使用步骤 1 引入库 2 读入数据 总结 前言 提示 这里可以添加本文要记录的大概内容 开发环境硬件普中科技 接线图在g
  • STM32 GPIO工作原理详解

    STM32 GPIO介绍 1 STM32引脚说明 GPIO是通用输入 输出端口的简称 是STM32可控制的引脚 GPIO的引脚与外部硬件设备连接 可实现与外部通讯 控制外部硬件或者采集外部硬件数据的功能 以STM32F103ZET6芯片为例
  • 跟着野火学FreeRTOS:第一段(任务定义,切换以及临界段)

    在裸机系统中 系统的主体就是 C P U CPU CP U 按照预先设定的程序逻辑在 m a i n
  • 1.69寸SPI接口240*280TFT液晶显示模块使用中碰到的问题

    1 69寸SPI接口240 280TFT液晶显示模块使用中碰到的问题说明并记录一下 在网上买了1 69寸液晶显示模块 使用spi接口 分辨率240 280 给的参考程序是GPIO模拟的SPI接口 打算先移植到FreeRtos测试 再慢慢使用
  • 串口通讯第一次发送数据多了一字节

    先初始化IO再初始化串口 导致第一次发送时 多出一个字节数据 优化方案 先初始化串口再初始化IO 即可正常通讯
  • STM32的HAL中实现单按、长按和双按功能

    我正在尝试实现单击 双击和长按功能来执行不同的功能 到目前为止 我已经理解了单击和长按的逻辑 但我不知道如何检测双击 至于代码 我使用计数器实现了单击和长按 但代码仅停留在第一个 if 条件上 bool single press false
  • 嵌入式开发--STM32G4系列片上FLASH的读写

    这个玩意吧 说起来很简单 就是几行代码的事 但楞是折腾了我大半天时间才搞定 原因后面说 先看代码吧 读操作 读操作很简单 以32位方式读取的时候是这样的 data IO uint32 t 0x0800F000 需要注意的是 当以32位方式读
  • STM32 上的位置无关代码 - 指针

    我已成功在 STM32 上构建并运行位置无关的代码 向量表和 GOT 已修补 一切正常 但我对这样的代码有问题 double myAdd double x return x 0 1 double ptrmyAdd double myAdd
  • PWM DMA 到整个 GPIO

    我有一个 STM32F4 我想对一个已与掩码进行 或 运算的 GPIO 端口进行 PWM 处理 所以 也许我们想要 PWM0b00100010一段时间为 200khz 但随后 10khz 后 我们现在想要 PWM0b00010001 然后
  • STM32F0、ST-link v2、OpenOCD 0.9.0:打开失败

    我在用着发射台 http www ti com ww en launchpad about htmlgcc arm none eabi 4 9 2015q2 为 STM32F0 进行编译 现在我想使用该集合中的 arm none eabi
  • STM32F4 定时器 - 计算周期和预分频,以生成 1 ms 延迟

    我在用STM32F407VGT6 with CubeMX 因此 我从通用定时器开始 但我被预分频值和周期值所困扰 基本上我想每隔一段时间生成一个定时器中断n 其中 n 1 2 3 ms 并执行一些任务 计算周期和预分频值的公式有很多变化 公

随机推荐