CC1010微控制器外设实战:定时器、串口、SPI与DES加密深度解析

发布时间:2026/7/26 14:33:46
CC1010微控制器外设实战:定时器、串口、SPI与DES加密深度解析 1. 项目概述CC1010微控制器的核心外设实战解析在嵌入式开发领域尤其是无线通信和物联网节点设计中选对一颗微控制器只是第一步真正考验开发者功力的是如何高效、精准地驾驭其内部丰富的外设资源。今天我们就来深入聊聊Chipcon后被TI收购的CC1010这颗经典的射频SoC芯片。它远不止是一个无线收发器其内核集成的8051微控制器配备了相当完整的外设套件包括多模式定时器、双串口以及硬件DES加密模块。很多开发者拿到数据手册看到那些寄存器位图和时序图就头疼更别提把理论公式转化成稳定可靠的代码了。我在实际项目中从简单的定时闪烁LED到复杂的串口协议解析、再到为无线数据包“穿上”加密外衣都深度使用过这些模块也踩过不少坑。这篇文章我就结合手册里的原理图和寄存器描述把这些外设的“脾气秉性”和实战用法掰开揉碎了讲清楚目标是让你看完就能在项目里用起来避开我当年走过的弯路。2. 定时器/计数器系统的心跳与精准时序的基石定时器是嵌入式系统的“心跳”几乎所有需要时间管理、频率测量或波形生成的任务都离不开它。CC1010的定时器资源比较丰富理解其工作原理和模式差异是精准控制的基础。2.1 定时器0/1经典8051架构的四种模式深度剖析CC1010的Timer 0和Timer 1沿用了标准8051的架构但理解其细节才能避免定时不准的坑。它们有四种工作模式由TMOD寄存器中的M1和M0位控制。模式013位计数器这是一个历史遗留模式将THx8位和TLx5位组成一个13位计数器。手册中的公式T (8192 - THx:TLx) * (12 - 8*CKCON.TxM) / f_xosc给出了溢出周期。但实践中我几乎不用这个模式因为13位不伦不类计算和重装都麻烦兼容性也差。除非你维护的老代码用了它否则建议直接忽略。模式116位计数器这是最常用、最直观的模式。THx和TLx组成一个完整的16位计数器从设定的初值向上计数到0xFFFF后溢出产生中断。其定时周期公式为T (65536 - THx:TLx) * (12 - 8*CKCON.TxM) / f_xosc。这里的(12 - 8*CKCON.TxM)是关键它对应时钟预分频器。当TxM0时分频比为12当TxM1时分频比为4。例如使用12MHz晶振(f_xosc)想要一个10ms的定时中断若设置TxM012分频则机器周期为1us。需要计数的机器周期数 10ms / 1us 10000。那么初值 65536 - 10000 55536 0xD8F0。所以TH00xD8,TL00xF0。注意公式中的THx:TLx指的是你重装的初值。如果你在中断服务程序中手动重装就代入你写的重装值如果你使用自动重装模式模式2或者在模式1中不重装让计数器从0开始则THx:TLx视为0。这一点手册提了但很容易被忽略计算时务必想清楚你的操作流程。模式28位自动重载这是做串口波特率发生器的“明星模式”。在此模式下TLx作为8位计数器THx保存重载值。当TLx溢出时不仅置位溢出标志TFx还会自动将THx的值重新装入TLx无需软件干预。其周期公式简化为T (256 - THx) * (12 - 8*CKCON.TxM) / f_xosc。它的优势是自动重装定时非常精确没有因软件重装延迟带来的误差。缺点是只有8位定时范围较小。在串口通信中我们正是利用其高精度和自动性来产生稳定的波特率时钟。模式3双8位定时器这是一个比较特殊的模式仅适用于Timer 0。在此模式下Timer 0被拆分成两个独立的8位定时器TL0和TH0。TL0使用Timer 0原有的控制位TR0, TF0, GATE0等可以工作在定时或计数模式。而TH0则固定为定时器模式并“借用”了Timer 1的控制位TR1和溢出标志TF1。此时Timer 1虽然停止计数但其寄存器值保持且仍可用于串口波特率生成模式2。这个模式在你需要三个定时器两个8位一个16位或8位自动重载用于串口时非常有用相当于扩展了定时器资源。两个8位定时器的周期公式均为T (256 - TYx) * (12 - 8*CKCON.TxM) / f_xosc其中TYx对应TL0或TH0的重装值。2.2 定时器2/3与PWM硬件波形生成的利器Timer 2和Timer 3是功能更强大的16位定时器集成了标准的定时器模式和硬件PWM输出功能通过TCON2寄存器控制。在定时器模式TCON2.Mx0下它们是一个16位的向下计数器。初值由T2PRE:T2或T3PRE:T3这个16位数预装。计数器使能TRx1后从该值向下递减减到0时触发中断EXIF.TFx置位并自动重装初值开始下一轮计数。中断周期公式为T_nInt (TnPRE * 256 Tn 1) / f_system。这里f_system是系统时钟。这里有个关键点TnPRE和Tn是8位寄存器但TnPRE存放的是重装值的高8位Tn是低8位。例如系统时钟为24MHz想要一个1ms的周期则需要的计数值 0.001s * 24,000,000 Hz 24000。换算成16进制是0x5DC0。那么T2PRE 0x5D高8位T2 0xC0低8位。代入公式验证(0x5D*256 0xC0 1) 24001周期约为1.00004ms误差极小。PWM模式TCON2.Mx1才是它们的亮点。在此模式下对应的引脚P3.4对应Timer 2 P3.5对应Timer 3被强制设置为输出无视P3DIR寄存器的配置。PWM的生成原理基于一个8位比较器。TnPRE寄存器设置PWM的周期频率Tn寄存器设置高电平的占空比。PWM周期T_nPWM (TnPRE 1) / f_system。注意这里TnPRE是8位值0-255所以PWM频率可调范围较广。例如f_system24MHz若T2PRE255则周期T256/24e6 ≈ 10.67us频率约93.75kHz若T2PRE0则周期T1/24e6 ≈ 41.67ns频率高达24MHz实际上受硬件限制可能达不到。PWM高电平时间T_nhPWM (Tn 1) / f_system。占空比 (Tn 1) / (TnPRE 1)。特殊值当Tn0时输出恒为低当Tn255且TnPRE255时输出恒为高因为Tn1256大于等于TnPRE1的最大值256。实操心得使用PWM模式驱动LED调光或电机时首先要根据所需的PWM频率确定TnPRE。例如驱动LED人眼对100Hz以上的闪烁不敏感我们可以选1kHz。若f_system24MHz则TnPRE f_system / f_pwm - 1 24000000/1000 - 1 23999这远超255说明直接生成1kHz的PWM会导致分辨率极低。此时需要先对系统时钟进行预分频如果支持或者使用定时器中断软件模拟PWM或者接受一个更高的PWM频率如10kHz此时TnPRE2399仍太大。实际上CC1010的硬件PWM更适合产生较高频率的方波几十kHz到MHz用于简单的蜂鸣器驱动或数字信号生成。对于精细的调光可能需要结合定时器模式用软件实现。2.3 看门狗与实时时钟系统的守护者与日历看门狗定时器是一个独立的8位计数器时钟来源于系统时钟经过2048到16384的可编程分频。其作用是防止程序跑飞。你需要定期“喂狗”向WDT.WDTCLR位写1如果超时未喂则产生系统复位。超时时间计算公式为T_reset 256 * 2^(11WDTPRE) / f_xosc。手册中的表格给出了典型值。这里有个大坑看门狗默认是使能的如果你在初始化阶段没有正确禁用它程序可能会在你不希望的时候被复位。禁用流程有严格顺序先置位WDT.WDTSE然后在16个系统时钟周期内清除WDT.WDTEN。最好用汇编或确保中间无中断的C语句块来完成。我常用的安全禁用代码如下假设操作寄存器宏已定义EA 0; // 关中断确保操作原子性 WDT | 0x10; // 设置WDTSE WDT ~0x08; // 清除WDTEN EA 1; // 开中断 while (WDT 0x08) { // 双重确认防止意外 // 如果WDTEN还在重复操作理论上不会进入 }实时时钟依赖于32.768kHz的外部晶振可以产生1到127秒的周期性中断。这对于需要低功耗定时唤醒的应用如每小时采集一次数据非常有用。使用前必须确保32kHz振荡器已启用通过相关时钟控制寄存器。只需设置RTCON.RT为所需的秒数然后置位RTCON.RTEN即可。注意RTC中断需要在中断系统中单独使能。3. 串行通信接口连接外部世界的桥梁CC1010提供了两个串口UART0和UART1大大增强了其通信能力。UART0常用于与主控或传感器通信UART1常预留给在线调试器但也可作通用串口。3.1 串口工作模式详解与配置陷阱两个串口都有四种模式通过SCONx寄存器的SM0_x和SM1_x位选择。模式0同步半双工这是一个同步移位寄存器模式。数据通过RXD引脚输入/输出TXD引脚输出移位时钟。每帧8位数据无起始/停止位。波特率固定为系统时钟的1/12或1/4由SM2_x位选择。这个模式常用于扩展I/O口驱动74HC595这样的移位寄存器。配置关键当作为输出时需要将TXDP3.1或P2.1对应的端口方向寄存器位设置为0输出而RXDP3.0或P2.0在硬件控制下自动切换方向。作为输入时则需要软件将RXD引脚先设置为输入模式。模式1标准异步8-N-1最常用的模式10位帧1起始位、8数据位、1停止位。波特率由Timer 1的溢出率决定公式为Baud (2^SMODx / 32) * Timer1_Overflow_Rate。其中SMODx位在PCONUART0或EICONUART1寄存器中用于倍频。Timer 1通常工作在模式28位自动重载其溢出率 f_system / (12 - 8*CKCON.T1M) / (256 - TH1)。因此最终波特率公式为Baud (2^SMODx / 32) * [f_system / ( (12 - 8*CKCON.T1M) * (256 - TH1) )]手册表23给出了一些常用波特率的配置示例。例如在11.0592MHz晶振下要得到9600波特率SMODx1T1M012分频查表可得TH10xFA250。计算验证溢出率 11.0592e6 / 12 / (256-250) 153600 Hz。波特率 (2/32) * 153600 9600。完美匹配。模式2和3异步9位数据这两种模式帧格式相同11位1起始、8数据、1可编程第9位、1停止区别在于波特率生成。模式2的波特率固定为f_system / 32或f_system / 64由SMODx选择。模式3的波特率生成方式与模式1相同由Timer 1决定。第9位数据TB8_x可用于多机通信的地址/数据帧标识。在SM2_x1时从机只在接收到的第9位为1地址帧时才产生中断从而过滤数据帧实现简单的多机网络。3.2 波特率计算与误差控制实战串口通信的稳定性核心在于波特率精度。CC1010使用11.0592MHz、22.1184MHz这类晶振不是没有道理的因为它们可以被1600整除11059200/96001152 115212*96能非常精确地产生标准波特率。计算步骤确定目标波特率和系统时钟频率f_xosc。选择Timer 1的工作模式几乎总是模式28位自动重载TMOD高4位设为0x20。选择SMODx通常先尝试SMODx1波特率加倍以获得更大的重载值范围和更低的误差。选择T1M即CKCON.T1M决定对系统时钟是4分频还是12分频。通常用12分频T1M0以获得更低的波特率范围和更好的精度。代入公式计算TH1重载值TH1 256 - (2^SMODx * f_xosc) / (波特率 * 32 * (12 - 8*T1M))计算出的TH1必须是整数否则会产生误差。计算实际波特率与误差实际波特率 (2^SMODx * f_xosc) / (32 * (12 - 8*T1M) * (256 - TH1))误差 (实际波特率 - 目标波特率) / 目标波特率 * 100%通常要求误差小于2%RS-232标准或更严如1.5%。示例系统时钟f_xosc18.432MHz目标波特率115200。假设SMODx1 T1M012分频。计算TH1 256 - (2 * 18.432e6) / (115200 * 32 * 12) 256 - 0.8333... 不是整数误差会很大。尝试SMODx0 T1M14分频。计算TH1 256 - (1 * 18.432e6) / (115200 * 32 * 4) 256 - 1.25 254.75 也不是整数。尝试SMODx1 T1M14分频。计算TH1 256 - (2 * 18.432e6) / (115200 * 32 * 4) 256 - 2.5 253.5。看来18.432MHz下很难精确得到115200。查手册表23在18.432MHz下要得到115200需要TH10xFF不对表里最高是57.6k。这说明CC1010在较高主频下受分频器和8位定时器限制可能无法直接生成很高的标准波特率。此时可能需要使用模式2的固定波特率或者降低通信波特率。避坑指南串口通信失败十有八九是波特率不对。除了计算一定要用示波器测量实际TXD引脚输出的位宽度来验证。一个起始位低电平的持续时间应严格等于1/波特率。例如9600波特率下起始位应持续约104us。测量这个时间是最直接的验证方法。4. SPI主控制器与DES加密模块扩展与安全4.1 SPI主控制器连接外部存储与传感器的通道SPI接口是连接Flash、EEPROM、SD卡、各类传感器的通用总线。CC1010的SPI是主模式通过SPCR、SPDR、SPSR三个寄存器控制。关键配置位SPR[1:0]时钟分频决定SCK频率。SCK f_xosc / (8 * 2^SPR)。例如f_xosc24MHz SPR00则SCK3MHz。CPOL时钟极性。0表示SCK空闲时为低电平1表示空闲时为高电平。CPHA时钟相位。决定了数据在SCK的哪个边沿采样和输出。CPHA0时数据在SCK的第一个边沿从CPOL状态跳变到反相被采样在下一个边沿输出。CPHA1则相反。必须与外设器件的数据手册要求严格匹配否则无法通信。DORD数据顺序。0表示先发送LSB最低位1表示先发送MSB最高位。操作流程配置P0.0(SCK)、P0.1(MO)、P0.2(MI)的引脚功能SPE1后SCK和MI方向被覆盖MO方向由P0DIR.1决定。根据外设要求设置SPCR的CPOL、CPHA、DORD、SPR。置位SPCR.SPE使能SPI。将要发送的数据写入SPDR硬件自动启动传输。等待传输完成。可以通过查询SPSR.SPA位为0时表示空闲或者更常见的是在写入SPDR后等待一段时间至少8个SCK周期的时间然后读取SPDR得到接收到的数据。注意写冲突在传输过程中SPSR.SPA1再次写入SPDR会置位WCOL标志且这次写入无效。好的做法是在写入前检查SPA位或者确保两次写入有足够间隔。两线制模拟手册提到了将MO和MI外部短接并通过软件控制P0DIR.1来模拟双向数据线如CC1000的接口。发送时设置P0DIR.10MO输出写SPDR。接收时设置P0DIR.11MO为高阻输入然后发送一个虚拟字节如0xFF来产生SCK时钟同时从SPDR读取输入的数据。这需要精细的时序控制。4.2 硬件DES加密/解密为无线数据加上安全锁在无线传输中对数据包进行加密是防止窃听和篡改的重要手段。CC1010集成了硬件DES加解密模块能显著减轻主控CPU的负担。核心概念DES数据加密标准使用56位密钥对64位8字节数据块进行加密/解密。工作模式模块支持输出反馈模式OFB和密码反馈模式CFB。这两种模式都能处理任意长度的数据不必须是8字节的倍数而不是简单的电子密码本ECB模式。CFB模式比OFB更安全推荐使用。密钥与数据存放密钥和待处理的数据都必须存放在外部RAM中并且起始地址必须8字节对齐即地址的低3位为0。CRPKEY寄存器指向密钥起始地址的高8位CRPDAT指向数据起始地址的高8位。初始化向量OFB和CFB模式需要8字节的初始化向量IV存放在CRPINI0-7寄存器中。加密和解密必须使用相同的IV。即使密钥相同不同的IV也会产生完全不同的密文增强了安全性。可以简单设置为全零但更好的做法是使用随机数。操作流程准备密钥将56位密钥7字节不含奇偶校验位存入外部RAM的8字节对齐地址。准备数据将明文加密或密文解密存入外部RAM的另一块8字节对齐区域长度由CRPCNT指定1-256字节0代表256字节。配置寄存器CRPKEY 密钥地址高8位。CRPDAT 数据地址高8位。CRPCNT 数据字节数。CRPINI0-7 初始化向量。CRPCON设置CRPMD模式选择、ENCDEC0加密/1解密、LOADKEYS本次操作是否加载新密钥、CRPIE是否使能中断。启动操作置位CRPCON.CRPEN。硬件开始处理。等待完成轮询CRPCON.CRPEN变为0或等待中断如果使能了。完成后CRPCON.CRPIF会被置位需要软件清零。注意DES中断与ADC共享所以还需要检查并清除EXIF.ADIF。获取结果加解密后的数据已经原地替换了原始数据In-place操作。直接从原数据地址读取即可。重要安全提示与性能考量密钥管理DES密钥本身安全性不高56位在现代计算机面前很脆弱。对于更高安全要求应使用三重DES3DES即用三个不同的密钥执行三次DES运算加密-解密-加密。这需要软件调用硬件DES模块三次。性能手册给出了时钟周期公式。例如加密16字节数据并加载新密钥LOADKEYS1所需周期数 2 25*16 21 423个时钟周期。在24MHz系统时钟下耗时约17.6us速度远快于软件实现。内存对齐地址必须8字节对齐否则行为未定义。在C语言中可以使用__xdata或__idata取决于内存模型定义数组并利用编译器特性或手动计算确保地址对齐。中断处理DES操作期间CPU可以处理其他任务。但要注意DES模块会访问外部RAM与CPU访问存在复用冲突可能会相互轻微延迟。在时间要求极其苛刻的场合需考虑此影响。5. 常见问题排查与调试经验实录在实际开发中理论通了不代表代码就能跑。下面是我在项目调试中积累的一些典型问题与解决方法。5.1 定时器相关问题问题1定时器中断不触发或触发频率不对。检查TRx位是否已置位启动定时器检查ETx和EA定时器中断是否已使能ET0/ET1总中断EA是否打开检查中断向量地址代码是否跳转到了正确的中断服务程序CC1010的Timer 0中断向量在0x000BTimer 1在0x001B。计算重装值仔细核对时钟源f_xosc、分频位TxM、工作模式、以及重装值的计算。最容易出错的是忽略了公式中的(12 - 8*CKCON.TxM)因子或者误用了十进制和十六进制。模式2的自动重装在模式2下你只需要初始化THx重装值TLx会在溢出时自动从THx加载。不要在中断里再给TLx赋值否则会打乱周期。问题2PWM输出没有波形或占空比不可控。引脚配置在PWM模式下TCON2.Mx1会强制覆盖P3DIR.4或P3DIR.5的方向。确保你没有在别的地方又把该引脚配置成了输入。Timer使能TCON2.TRx必须置1。TnPRE和Tn赋值顺序理论上没有严格要求但最好先设置TnPRE和Tn最后再置位TRx。输出恒定电平检查Tn的值。如果Tn0输出恒低如果Tn255且TnPRE255输出恒高。确保Tn值在合理范围内0 ≤ Tn ≤ 255。频率过高用示波器测量。如果设置的PWM频率接近或超过系统时钟频率实际波形可能会畸变或出不来。5.2 串口通信问题问题1自发自收正常但与其他设备通信失败。电平匹配CC1010的UART是TTL电平0V/3.3V。如果对方是RS-232电平±12V需要加MAX3232这类电平转换芯片。如果对方也是TTL确保共地。波特率误差用示波器测量位宽。误差超过3%通常会导致通信不稳定。换用11.0592MHz等标准晶振。停止位数量模式1是1位停止位。有些设备配置可能要求2位停止位CC1010不支持需对方调整。硬件流控CC1010的UART不支持RTS/CTS硬件流控。如果对方需要且数据量大会导致缓冲区溢出需要用软件XON/XOFF或额外的GPIO模拟流控。问题2接收数据乱码或丢失。中断冲突串口接收中断RI是查询式置位的。如果中断服务程序执行时间过长可能在处理上一字节时下一字节已经到来并覆盖了SBUF导致丢失。确保中断服务程序尽可能短或者使用缓冲区。SM2位的影响在模式2/3下如果SM21则只有接收到第9位为1的帧才会触发RI中断。检查SM2配置。电源噪声在无线收发期间电源纹波可能较大影响UART的采样精度。确保电源去耦良好并在UART线上串联小电阻如22欧姆并加对地电容如10pF以滤除高频噪声。5.3 SPI与DES模块问题问题1SPI无法读取外设数据。CPOL和CPHA这是最可能的原因。仔细对照外设芯片手册的时序图确定其在SCK的哪个边沿采样数据空闲时SCK是高还是低。CPOL和CPHA有4种组合逐一尝试。片选信号CC1010的SPI主控制器不自动管理片选CS。你需要用另一个GPIO引脚手动控制外设的CS。确保在通信前拉低CS通信后拉高。时钟频率太快有些低速SPI设备如某些传感器最高SCK频率只有几百kHz。通过SPR位降低CC1010的SPI时钟。数据顺序检查DORD位匹配外设的MSB/LSB First要求。问题2DES加密/解密结果不正确。地址对齐百分之九十的问题出在这里。确认密钥和数据块的起始地址是8的倍数。可以通过if ((uint16_t)key_addr 0x0007) ! 0)来检查。初始化向量加密和解密必须使用完全相同的IV。确保在解密前CRPINI0-7被设置为与加密时相同的值。密钥格式DES算法使用的密钥是56位但通常以64位8字节形式给出其中每字节包含1位奇偶校验位通常忽略。CC1010的硬件要求输入的是去掉奇偶校验位的7字节。例如标准64位密钥0x0123456789ABCDEF你需要将其转化为56位7字节形式存储。具体转换需要参考DES算法标准通常是将每字节的最低位移除。操作模式混淆OFB和CFB模式的结果不同。确保加密和解密时CRPCON.CRPMD设置一致。内存覆盖DES是原地操作。如果你加密后还想保留明文必须在加密前将明文复制到另一个缓冲区。调试这些外设逻辑分析仪是神器。它可以同时抓取多路GPIO定时器输出、PWM、UART的TX/RX、SPI的CLK/MOSI/MISO/CS的时序波形让你直观地看到寄存器配置是否产生了预期的硬件行为是排查通信和时序问题最快最准的方法。