马上十月份左右就开始电赛啦,我之前参加过两届电赛,但是万年省二……
今年的电赛应该是参与不了了
抽了几天的空,大概五天的时间,写了一点点TI单片机的底层程序,在码云上啦,代码地址

首先去获取资料

官网得到的资料我跟代码一起放到码云上,在tool文件夹下面。

我手上的是一块LaunchPad 评估套件,芯片是tm4c123gh6pm,先上官网找资料。
在索引栏直接搜索tm4c123gh6pm,可以找到

点进去,看到
就是我的开发板,
TM4C123G LaunchPad 评估套件是一个低成本评估平台,适用于基于 Arm Cortex-M4 的微控制器。TM4C123GH6PM MCU 配备 80MHz Arm Cortex-M4F CPU、256kB 闪存和 32kB SRAM,为 USB 主机/器件/OTG 和两个 12 位 ADC 模块提供集成的 USB 2.0 支持。TM4C123GH6PM 还包括多个串行通信通道,例如 UART、SPI、I2C 和 CAN。TM4C123G LaunchPad 设计的亮点是 TM4C123GH6PM USB 2.0 器件接口以及休眠和 PWM 模块等其他器件功能。EK-TM4C123GXL 具有用于自定义应用的可编程用户按钮和 RGB LED。可堆叠接头提供了连接 BoosterPack™ 插件模块的接口,可让您通过德州仪器 (TI) 的 BoosterPack 生态系统轻松扩展 TM4C123G LaunchPad 的功能。TI 开发的 TivaWare SDK 为 TM4C123G LaunchPad 提供所有外设的驱动程序以及数十个应用的示例代码。
说得很明白,板子上的其它资源我是看的开发套件里的那一张纸来的,还是很贴心的

回到官网,我找到了sdk、芯片手册、电路图。

SDK我下载的这个,选的这个芯片的,然后得到了一个.exe文件,运行后就会得到一个文件夹,重点看example文件夹里的东西

电路图也在这里,解压里面有pdf原理图,我主要是看这个原理图

芯片手册也在下面

然后再说说我的代码

我按照我写的顺序来说
第一个template用来测试一下。工程借鉴的sdk\examples\boards\ek-tm4c123gxl\hello这个例程,发现它的启动文件挺有意思的,我看不到中断向量的名字,在进入main函数之前也没有系统的初始化操作。移植关于仿真和下载程序我刚开始用的usb,发现那个一在线调试就卡住了,所以后来把它的swd仿真引脚接出来了,改用dap来烧录和调试。关于这个配置系统时钟,官方代码是SYSCTL_SYSDIV_4,频率太低了,我去手册里看了一下,看芯片手册223页(Clock Control),发现官方是按照50M来的,这个给我后面定时器配置上带来了一些麻烦


第二个是led工程,老规矩先点灯,这个板子上是有一个rgb灯的,通过三个引脚控制在,而且是用三极管上拉,高电平点亮,LED_R —> PF1,LED_B —> PF2,LED_G —> PF3


第三个是timer定时器工程,这里我做了一个任务调度,这里有一个坑,就是前面说到的SysCtlClockSet函数第一个参数,官方说是80M,但是官方例程是50M,具体看前面的那张图。然后我以为设置为SYSCTL_SYSDIV_1可能会更高主频,事实完全不是那么回事儿。最终进入它的定义,选择了SYSCTL_SYSDIV_2_5对应的是官方所说的80M主频,然后再去计算定时器技术什么的产生中断。这里我搞了一个时间片调度,不难理解。

这个芯片定时器有16/32/64几种模式,一个定时器包含A\B两个子定时器
有6个这样子的定时器t0~t5,不过t4和t5两个定时器的IO是调试引脚
具体看芯片手册704页(General-Purpose Timers)
关于优先级,值越大优先级越低,因此级别0是最高的中断优先级
每个中断的可编程优先级有0-7共八个,我也没弄明白,看例程来的,定义在了main.h里,USER_INT0~USER_INT7,具体看芯片手册124页(Nested Vectored Interrupt Controller (NVIC))和164页( Interrupt Priority Levels),关于优先级应该是有一个初始化操作的函数的,没有去细究,这里是瞎设置的。借鉴了一下无名创新飞控的程序,发现它把初始化里面的一段搞成.o文件了我不知道它是怎么初始化的,这边的优先级什么的直接瞎给的,不过一定是有一个类似于中断分组的初始化函数的,我不知道是什么。


第四个工程是PWM定时器工程,芯片有两个PWM模块
总共可以产生16路PWM,一个PWM模块8路
一个PWM模块有四个发生器,一个发生器可以产生两路PWM
同一个发生器的产生的PWM频率是一样的
关于频率和占空比,就是计数
主频设置为80M,然后SysCtlPWMClockSet(SYSCTL_PWMDIV_8)分8频,也就得到计数一次需要1/(80M/8)s = 0.1us
所以此时我将PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0, period)中period设置为1000就是10KHZ
占空间PWMPulseWidthSet(PWM0_BASE,PWM_OUT_1,width1)中width1设置为500就是50%占空比
0占空比默认是高电平,挺奇怪
PB6 —> PWM0;
PB7 —> PWM1;
PB4 —> PWM2;
PB5 —> PWM3;
开发板上PB7与PD1相连,PB6与PD0相连,不知道为什么要把这个连在一起。。。
具体看芯片手册1230页(Pulse Width Modulator (PWM))


然后是串口
PB0 —> UART1_RX;
PB1 —> UART1_TX;
PD6 —> UART2_RX;
PD7 —> UART2_TX;
接受函数是UARTCharGet
发送函数是UARTCharPut
这里有一个地方,开发板上PA0与PA1莫得,是跟调试引脚搞出来的,看下原理图就知道在哪里。遇到了一个事情比较玄学,串口0的接收端不能用,串口1正常,串口2也不正常,这个在后面得到了解决。


然后是ADC
芯片手册799页Analog-to-Digital Converter (ADC)
有三个ADC模块,12个ADC引脚
ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_CH0 |ADC_CTL_END | ADC_CTL_IE)里的ADC_CTL_CH0代表引脚
第二个参数ui32SequenceNum可以看芯片手册799的图,据我理解就是不同通道用不同的ui32SequenceNum
第三个参数ui32Step据我理解就是触发到来时候的采集顺序(这个不清楚)
PE3 —> AIN0
PE2 —> AIN1
PE1 —> AIN2


然后是key按键中断
几乎所有IO都可以有外部中断,相同端口共用一个中断号,这个跟32很像
开发板上有两个按键,PF4 —> SW1 , PF0 —> SW2
我又多加一个中断,PB2
我最终代码里面旋转编码器就是靠外部中断来数的
写了一个解锁IO的东西,关于这部分,看芯片手册684-685页
这个锁确实烦人,芯片手册679页有需要解锁的说明
解锁程序借鉴gpio_jtag例程


最后是eeprom程序
这个芯片内部有2K的eeprom
用来保存参数
注意那个写入、写出的数量是4的倍数就行
最终烧录这个程序,现象是这样子的

关于硬件电路板

扩展电路是我分配的引脚,然后交给另一个实验室的同学做的,需要的可以找他要(QQ:2569664884)

over,这个我可能不会怎么去折腾了,如果没有特殊需要用到TI芯片应该是不会去维护啦,写个博客记录交流一下。除了这个,之前还薅过NXP的几款芯片的底层,用的也是keil,芯片是kv58\kv11,还有英飞凌家的XMC4800,都是比赛接触的,不过这些太久远了不好总结了。我比较喜欢自己花时间去写底层,熟悉一下资料的查找和利用。