一、入门介绍
32位微控制器
有丰富外设:AD(采样)、PWM(脉宽调制,输出脉冲方波)、ECAP(捕获脉冲信号)、EQEP(正交编码器的解码单元)、SCI(串行通信接口RE232\RS484\RS422)、SPI(串行外设接口)、ECAN()、CPU定时器()、完善的中断机制
C82x处理器---使得c2000优于普通MCU:4个集成式高速片上硬件加速器,同时具有MCU和DSP两种功能
(浮点加速器、复数数学和CRC单元(VCU)加速器、三角数学单元(TMU)加速器、控制速率加速器(CLA))
C2000应用:数字电源、电机驱动、电力电子新能源、电力系统、工业自动化、汽车电子。(高性能)
分类(性能/成本):piccolo(入门级)、delfino(高性能和扩展)
C200处理器芯片:
TMS:ti公司合格产品
320:TI DSP系列
F:Flash Eeprom(核电压1.8V/1.9V I/O口电压3.3V)
28:芯片型号
P:芯片封装信息4
65X:温度范围
开发c200所需软硬件:
软件:code composor studio(CCS)写软件
硬件:C2000电路板LauchedPad 运行
仿真器:JTAG连接开发板、USB连接软件
二、资料处理
手段:书、芯片手册
了解:处理器性能、外设、引脚
通用学习:系统控制部分systemcontrol, 存储器、映像、CMD、中断系统、CCS程序架构
方法:跑例程+写项目
竞赛:电子竞赛
建议:多看多学多交流
获取资料软件
ControlSUITE:TI资料库
获取方式:TII官网(注册账号)—搜索框“controlsuite“ –download ---- 打开软件—查看
三、安装CCS+新建工程
安装:TI 官网 ---- TOOLS AND SOFTWARE---- code composer studio-IDE ---- get CODE COMPOSER STUDIO ---- download the lasted version ---- 离线安装包windows ---- 下载完成后setup.exe ---- 退出杀毒软件提醒,选YES ---- accept条款 ---- 安装路径(不能含有中文字符) ---- 处理器勾选“C200 32-bit real-time MCUs“ ---- 仿真器驱动支持包(默认)---- app center不选 ---- finish ---- 创建快捷方式。
第一次点开ccs需要建立工作空间路径—D:/myccs ---- lauch
新建工程:工具栏“Project“ ---- new ccs project ---- target”选择芯片型号(TMS320F28P650DK9)”, connection”选择仿真器(Texas Instruments XDS110 USB Debug Probe)“, project name “输入名字”, compiler version”TI v22.6.1.LTS”, project templates and examples”empty project(with main.c)” ---- finish
备注: .cmd是存储器映像文件
Targetconfigs--.ccxml文件里包含芯片信息
编译文件: 右键单击工程文件 ---- build project ---- 变异成功后debug文件夹会出现一个与工程名一样的.out的可执行文件----/工具栏“小虫子“快捷键
四、CCS中调试文件
将完整文件导入到ccs; 工具栏“project“ ---- import ccs projects ---- browse”选择文件” ---- finish
烧录工程文件导DSP开发板中:右键工程文件—degub as ---- 1 code composer debug section----/工具栏“小虫子“快捷键 ----
运行:resume快捷键
暂停:suspend快捷键
停止:terminate快捷键,重新开始的话需要重新烧录文件
设置断点:debug界面,双击行数。取消也是双击。
查看实时变量:选中变量,右键“add watch expression“。右上角”continuous refresh“实时更新数据,数据产生变化时背景位黄色。改变数据格式:选中数据,右键number format。改变变量观测顺序:直接拖动改变位置。
查看运行时间:设置断点----运行----工具栏“Run“----clock----enable----屏幕右下角出现一个”时钟图标“----再次运行----停止时查看右下角数据:显示”时钟周期数“----计算运行时间=周期数*1/f(中断程序运行时间不能超过中断时间)
曲线观测变量:原理:把观测变量放到数组里面,通过点画曲线。tools----graph----single time ----acquisition buffer size设置为该变量数组大小。Dsp data type设置为该变量类型。Index increment增量设置为1. Qvalue=0. Sampling rateHz = 1. Start address设置为数组名字。Display data size设置为数组大小----OK。设置持续更新。
五、 存储器映像及CMD文件
存储器分类:RAM掉电丢失数据,程序运行速度快;Flash掉电不丢失数据,程序运行速度比ram慢。一般将程序固化到Flash中,运行时由cpu copy到RAM中运行。
存储器映像:memory map每个存储单元都有一个固定地址。
(地址看作门牌号,数据看作快递,cpu看作快递员)
Cmd文件:规定了数据和代码具体的固定存储规格(地图)。
Sections代码:将数据段/代码段存储到存储器空间。
如何将数据存储到指定空间?
例如:将数组x[100]储存到外扩RAM(起始地址0x100000)中?
主函数中:
Float x[100]; //定义一个数组
#pragma DATA_SECTION(数组名, “数据段名”); //定义一个数据段
Cmd文件中:
地址名: origin = 0x100000, length = 0x004000 //地址长度不能超过存储器本身的长度,也不能低于数组长度。先设置为1K大小。
在sections段:.数据段名 :>地址名, PAGE = 1
六、中断地址
什么是中断interrupt?
假设你写代码叫做程序,这个时候老板打电话过来,因为老板的电话比现在写代码更重要,所以要接电话,接电话就叫中断。
顺序执行
初始化—循环—中断
Cpu中断、PIE中断、外设中断
中断事件
电源
外设:cpu定时器\EPWM\ADC\ECAP\EQIEP\SCI\SPI\CAN. 根据中断可分为软件中断(程序内通过指令中断)、硬件中断(处理器的硬件中断,外设就属于硬件中断)。可屏蔽中断(通过寄存器控制允许/不允许中断产生)/不可屏蔽中断(cpu无条件响应中断)。
中断优先级(多个中断同时向cpu发出请求)
每个外设中断都会在寄存器都会有对应的标志位(表示中断事件是否发生)和使能位(表示中断是否被使能,是否向cpu请求中断)。
定时器0(TINT0)
PIE中断:外设中断的管理系统。组序号和组内序号,都是序号小优先级高。三个寄存器:PIEIFRx标志位,PIEIERx使能位,PIEACKx应答位(cpu是否正在响应cpu中断,不用时应该清零)。
CPU的寄存器:IFR(标志位),IER(使能位),EINT(使能全局中断),EDIS(禁止所有中断)
C2000的三级中断系统:外设级----PIE级----CPU级
七、时钟和系统控制
外部时钟源-晶振:无源(工作时无外接电压,有负载电容)/有源(工作时有外接电压Vcc,),封装(直插/贴片)
晶振频率Hz:20M/12.5M/30M/50M(32.768)
外部晶振---振荡器OSC---锁相环PLL(倍频)---形成clk信号给cpu
主频(频率越高,性能越好): F28335:30M—150M
C28346:20M—300M
F833TD:200M/核
CLKN(主频SYSCLKOUT)通过LOSPCP(低俗外设时钟寄存器)降低频率后变成LSPCLK(低速时钟)供给对于时钟要求不高的外设,或者通过HISPCP(高速外设时钟寄存器)提高频率后变成LSPCLK(高速时钟)
外设 |
所用时钟源 |
ADC |
HSPCLK |
eCAN |
SYSCLKOUT/2 |
eCAP |
SYSCLKOUT |
ePWM |
SYSCLKOUT |
eQEP |
SYSCLKOUT |
I2C |
SYSCLKOUT |
MCBSP |
LSPCLK |
SCI |
LSPCLK |
SPI |
LSPCLK |
Table 7.1 28335的时钟
ADC:采样率
通信:波特率
外设时钟需要寄存器使能才能使用。
低功耗:只使能工作所需时钟,降低寄存器功耗。
八、通用输入输出引脚GPIO
GPIO: general purpose input output
引脚复用:为了节省资源,既可以作为I/O,也可以作为功能引脚。通过寄存器决定引脚种类。
以28335为例
LQFP.176引脚: 电源类、AD引脚、系统相关(JTAG\GPIO)
GPIO引脚特点:
输入口电平,与TTL电平兼容
>20V,认为是高电平
<1.2V, 认为是低电平
输出 3.3V高电平 0V低电平 CMOS电平 驱动能力4mA
EALLOW保护语句:开始写
… //语句
…//语句
…//语句
EDIS:结束语
GPIO寄存器:
控制寄存器:GPxMUX选择 GPxDIR方向 GPxPUD上拉 GPxQsel输入限定选择
数据寄存器:GPxDAT数据 GPxSET置位 GPxCLEAR清除 GPxTOGGLE翻转
外部中断源
低功耗模式唤醒选择寄存器
GPxMUX功能选择:每两位作为一个选择口
GPxDIR方向:每位都决定引脚方向 0输入 1输出
GPxPUD上拉: 默认有一个上拉电阻,从不定态上拉至固定态。上电时。默认上拉是禁止的,而其他上拉复位后默认是使能的。0开启 1禁止
GPxQsel输入限定选择:作为输入时,采样。DSP连续采样来判定电平高低。连续n次全部相同电平才能判定电平(优点:滤波,提高稳定性)。
GPxDAT数据 :0低 1高
GPxSET置位:只能作为输出 0无效 1高电平置位
GPxCLEAR清除:只能作为输出 0无效 1高电平清除
GPxTOGGLE翻转:只能作为输出 0无效 1高电平翻转
九、写个GPIO程序控制LED
目的:用GPIO控制28335上面的“RUN”灯,周期性闪烁
DSP是串行执行处理器
步骤:
- 新建工程: 工具栏project----new CCS project----target选择芯片型号、connections选择仿真器、project name工程名字、路径workspace、project templates and examples选择empty----finish。
- Workspace路径下:准备cmd文件、include文件(28335头文件,通常不需要更改)。建立source文件夹:所有c语言文件放这。
- 回到ccs,打开main.c,头文件已经准备好。
- 检查GPIO时钟是否使能确保外设正常工作。F3快捷键—快速定位函数。
- EALLOW { GPAMUX对应引脚设置为普通I/O口。GPADIR设置为1输出引脚。} EDIS
- DINT; //禁止CPU所有中断
- InitPieCtrl(); //初始化所有PIC控制系统寄存器
- IER=0x0000; //禁止所有cpu中断,
- IFR=ox0000; //清除所有标志位
- InitPieTable(); //
- EINT; //全局中断使能
- 可以加一个空的for循环使得程序不会结束。For循环里写对应RUN灯引脚点亮,插入延时DELAY_US();灯灭;延时。
- 编译 build project
- 烧录: 在targetConfigs文件夹里打开.ccxml文件,点击Test Connection检查软件是否和仿真器连接,测试成功显示succeeded。
Debug as等待烧录完成后,点击运行resume,板子的led显示灯会闪烁(如果有这个功能),
十、CPU定时器
28335里面有3个定时器
4个输入:reset、 timer reload、sysclkout、TCR.4(定时器启动)
一个输出:!TINT
XH:X XH代表寄存器的高位 后一个X代表寄存器低位
工作原理:
PRD定时器装载到TIM计数器里,每隔一个TIMCLK信号的TIM计数器会-1直到0后生一个TINT信号输出。TIMCLK信号由TDDR分频器装载到PSC预定标计数器内每隔一个SYSCLKOUT系统时钟信号-1直到0输出。
分频器TDR,周期寄存器PRD,这两个值固定的情况下cpu完成一个周期的计数需要多少时间(换言之,周期是多少)?
Time=(1+PRD)*TIMCLK 单位:s秒
TIMCLK=(1+TDR)*SYSCLKOUT
Cpu定时器周期中断:0优先级高
十一、结合CPU定时器和GPIO实现跑马灯
跑马灯原理:LED按照顺序从前往后逐个点亮熄灭,又从后往前,循环。
每个灯点亮时间要保证肉眼可见:加入延时
状态切换保持时间:加入延时
电路板共阳极3.3V,接二极管,电阻,接阴极接GPIO。当GPIO为低电平时,二极管导通,灯亮。
在timer.c内写程序:
头文件
InitSysCtrl(); //初始化
InitGpio(); //初始化GPIO,MUX=0功能为IO口,DIR=1 io口作为输出
InitCpuTimer(); //初始化CPU定时器
DINT; //禁止所有中断
InitPieCtrl(); //初始化PIE中断
IER= 0x0000; //禁止cpu中断
IFR=0x0000; //清除cpu中断标志位
InitPieVectTable(); //初始化PIE中断向量表
EALLOW; //
PieVectTable.TINT0 = &ISRTimer0;
//指定TINT0的入口函数,也可以使用系统默认的中断函数
EDIS; //
IER |= M_INT1; //使能CPU中断1。M_INT1=0x0001,IER或上M_INT1后为1,使能
PieCtrlRegs.PIEIER1.BIT.INTx7 = 1; //使能PIE中断7
EINT; //使能全局中断
ERTM; //使能全局实时中断DBGM
ConfigCpuTimer(&CpuTimer0,150,1000000);
//配置cpu定时器,使用定时器0,时钟频率MHz,定时时长us
StartTimer(); //启动定时器
for( ; ;) //写跑马灯
在defaultIsr里定义跑马灯任务函数
十二、EPWM
PWM:pulse width modulation 脉宽调制:可以调节宽度的方波
作用:驱动各种开关器件,例如IGBT
常用参数:
频率f:
周期T(频率倒数)
幅值(低电平到高电平的电压差)
占空比D=高电平的时间H/T
相位
死区时间
操作:频率f通常是固定的,通过调节占空比D实现PWM功能
互补PWM
PWM1和PWM2是完全对称互补的方波,
但实际上,由于器件的开关特性,并不会准时的开通或关断,这就可能导致了电路短路。
解决方法:一个完全关闭以后,另一个延时再开通,这个延时称作死区时间Deadtime。
三相
三个PWM错开一定的角度,称作相位Phase。
以28335为例,有6个EPWM模块,内部结构完全一样,功能也完全一样
每一个EPWM有7个子模块:TB时间基准、CC比较器、AQ动作限定、DB死区时间限定、PC斩波、ET事件触发中断、TZ故障捕获。
(斩波:一个T里面变成多个的高频T)
(TZ:如果电路发生故障,马上封锁EPWM模块,起到保护电路作用)
一个EPWM模块可以输出两个EPWMA+EPWMB,即可以独立输出也可以互补输出。
1. TB和CC
Time Base时间基准
Counter Compator比较功能
EPWM生成PWM:
方法:载波(三角波)、调制波。载波频率通常是调制波的整数倍。载波和调制波的交点处电平跳变产生PWM波形。
SPWM:三角载波同正弦调制波。
TB:
作用:产生同步信号;计数;
同步用处:例如同时使用多个EPWM模块,需要同步
计数:计数寄存器、周期寄存器
CC:
工作(增减计数)在三角载波中,计数寄存器CTR与比较寄存器作对比。一旦CTR=CMP,触发比较事件(事件也有可能是CTR=0或者CTR=PRD,根据情况设置),PWM发生电平跳转。
PRD寄存器决定了PWM的周期/频率
CMP寄存器决定了PWM的占空比
计数器和周期的关系:
增/减计数器生成PWM的周期=PRD+1
增减计数器生成PWM的周期=PRD*2
EPWM模块有两个输出EPWMA和EPWMB分别需要对应两个比较寄存器CMPA和CMPB。
TB计数时钟TBCLK,由SYSCLKOUT分频而来:
受两位控制,HSPCLKDIV,CLKDIV。对于HSPCLKDIV功能位是x,当x=0时,分频系数是1。x不等于0时,分频系数是2x。当x=0时,TBCLK的频率=SYSCLKOUT/2^Y。当x不等于0时,TBCLK的频率=SYSCLKOUT/(2x * 2^Y)。对于CLKDIV功能位是y,当y=0时,分频系数是2^y。
EPWM的周期=PRD的周期/TBCLK的周期。
EPWM的同步链条:
同步输入信号EPWM1SYNCI来自于外部输入GPIO,输出可以给到epwm2或者4。3从2获得,6从5,5从4。 同步功能可以使用也可以忽略。
2. AQ和DB
AQ的作用:设定这两个引脚在不同计数器事件发生的时候,引脚电平如何变化来产生PWM波形。
可能触发的6个事件:CTR=PRD; CTR=0; CTR=CMPA; CTR=CMPB; CTR_Dir=0/1;
CTR_Dir表明是增或者是减计数器。
事件可能的4个结果:无变化; 高电平; 低电平; 电平翻转;
DB作用:避免短路,尤其在大功率电路中
图:DB内部结构
DBCTL死区控制寄存器
功能位IN_MODE:有00,01,10,11分别代表S4,S5开关的选择
极性位POLSEL:选择开关S2,S3是否取反
OUT_MODE::选择开关S1,S0的输出
图:典型的死区方案(具有死区互补输出的两路PWM信号)
DBRED死区上升沿寄存器:作用是延时; 时间=DBRED*TBCLK
DBFED死区下降沿寄存器:作用是延时; 时间=DBFED*TBCLK
3. PC和TZ
PC PWM Chopper斩波:通过高频载波信号对由AQ/BD输出的PWM波形调制。
应用:控制高开关频率的功率器件。
可以选择通过PC,也可以不经过PC直通输出。
PCCLK=SYSCLKOUT/8
只有一个控制寄存器PCCTL,通过赋值CHPFREQ(取值范围0~7)和CHPDUTY(取值范围0~6)得到:
PC的频率=SYSCLKOUT/8(CHPFREQ+1)
占空比D=(1+CHPDUTY)/8
将原来的PWM波形与高频调制信号PSCLK做逻辑与生成斩波。每个周期内的第一个载波脉冲one shot宽度可编程(加宽),目的:使得第一个周期的脉冲携带较大的能量,功率器件能可靠的开通。首次脉冲宽度可以通过PCCTL[OSHTWTH]来设置,取值范围0~15.
首个脉冲宽度Tfirst_pulse=Tsysclkout *8* (1+OSHTWTH)
OSHT信号和斩波信号做或与XOR运算得到首脉冲调制的斩波信号。
TZ trip zone故障捕获
6个输入引脚,外部信号可以通过这几个引脚模拟外部故障或其他事件,从而EPWM模块可以对此发出响应(比如将所有PWM信号置为低电平),起到保护作用。
输入可以配置成两种触发方式:
单次触发one shot trip:一旦触发,会根据TZCTL寄存器设定的情况强制输出EPWM且保持不变,直到人为清除故障信息并复位EPWM。
周期性触发cycle-by-cycle trip:以TBCLK计数周期为单位,在每个周期内,如果捕获到故障信号,EPWM的输出立即强制等于TZCTL设定的状态。当TBCLK计数到0且故障不存在时,EPWM的强制状态清除。
4. ET
事件触发子模块
CTR:时间基准子模块里的计数器寄存器
CTR_DIR:决定增计数/减计数
EPWMxINT:中断请求信号,请求PIE
SOCA/B:启动转换的信号。启动AD外设(可以通过软件启动,或者外设启动)。
产生ADC启动信号ADCSOC
ETSEL选择事件触发方式,当SOCACNT计数器计数到足够次数的事件后,产生脉冲信号并且ETFLG标志信号生成,输出SOCA启动信号。与EPWM信号不同的是,不管FLG信号是否挂起,只要SOCACNT计数到次数后就会产生脉冲信号。
5. ADC
定义:将物理信号转换成数字信号的处理器。
指标:
精度:位数越高精度越高价格越高
信号范围:引脚接收电压信号的范围 0-3V? 正负3V?
转换时间:
采样率:每秒钟采样次数 AD7606最高采样率能达到200kps
6. 配置EPWM
(sInitEPwm函数)
- CpuSysRegs.PCLKCR0.bit.TBCLKSYNC 停止使用TC clocks。
- AQ模块(8个EPwmnRegs都要配置,n:1~8)
- AQSFRC.RLDCSF 选择AQ的装载RLD数据方式
- TZ模块(8个EPwmnRegs都要配置,n:1~8)
- TZFRC.OST one-shot trip 0:只写0; 1:force ost和写FLG信号
- 输出信号(只用了EPWM1)
- EPWMSYNCOUTEN
- SWEN: 使能TBCTL.SWFSYNC
- ZEROEN: 使能触发“TBCTR=0x0000”事件使输出EPWMxSYNCOUT。
- CMPBEN: 使能触发“TBCTR=CMPB”事件使输出EPWMxSYNCOUT。
- CMPCEN: 使能触发“TBCTR=CMPC”事件使输出EPWMxSYNCOUT。
- CMPDEN: 使能触发“TBCTR=CMPD”事件使输出EPWMxSYNCOUT。
- DCAEVT1EN: 使能触发“DCAEVT1.sync”事件使输出EPWMxSYNCOUT。
- DCBEVT1EN: 使能触发“DCBEVT1.sync”事件使输出EPWMxSYNCOUT。
- EPWMSYNCOUTEN
- 输入信号(8个EPwmnRegs都要配置,n:1~8)
- EPWMSYNCINSEL.SEL 选择定义在“Epwm sync selection”表格中的输入值
- 异步信号使能(8个EPwmnRegs都要配置,n:1~8)
- TBCTL.PHSEN 选择是否使能TB PHASE REG,
- TBCTL2.PRDLDSYNC 选择何时装载shadow到active period reg
- EPWMXLINK
- TBRDLINK 选择写到哪个Epwm模块中的TBPRD
- CMPALINK 选择写到哪个Epwm模块中的CMPA_CMPAHR
- CMPBLINK 选择写到哪个Epwm模块中的CMPB_CMPBHR
- 循环写EPWMnRegs(8个EPwmnRegs都要配置,n:1~8)
- TB模块
- TBCTL
- HSPCLKDIV 高速时钟预分频TBCLK=EPWMCLK/(HSPCLKDIV*CLKDIV)
- CLKDIV 分频倍数
- PHSDIR 相位方向(只有TB计数器设置为增减记数时启用)
- CTRMODE 计数模式
- PRDLD 选择ACTIVE PERIOD REG是否从shadow reg装载
- TBCTR TB计数器初始清零
- TBPRD 设置TB初始周期
- TBCTL
- CMP模块
- CMPCTL
- SHDWAMODE 选择CMP是否使用shadow reg
- SHDWBMODE 选择CMP是否使用shadow reg
- LOADAMODE 选择CMPA CTR从SHDW的装载模式
- LOADBMODE 选择CMPB CTR从SHDW的装载模式
- CMPCTL
- AQ模块
- AQCTL
- SHDWAQAMODE 选择AQ A是否使用shadow reg
- SHDWAQBMODE 选择AQ B是否使用shadow reg
- LDAQAMODE 选择AQ A CTR从SHDW的装载模式
- LDAQBMODE 选择AQ B CTR从SHDW的装载模式
- AQCTLA(没用到,全部no action)
- CAU UP增计数TBCTR=CMPA时的反应
- CAD DOWN减计数TBCTR=CMPA时的反应
- ZRO TBCTR=ZERO时的反应
- PRD TBCTR=TBPRD时的反应
- CBU UP增计数TBCTR=CMPB时的反应
- CBD DOWN减计数TBCTR=CMPB时的反应
- AQCTLB(没用到,全部no action)
- CAU UP增计数TBCTR=CMPA时的反应
- CAD DOWN减计数TBCTR=CMPA时的反应
- ZRO TBCTR=ZERO时的反应
- PRD TBCTR=TBPRD时的反应
- CBU UP增计数TBCTR=CMPB时的反应
- CBD DOWN减计数TBCTR=CMPB时的反应
- AQTSRCSEL
- T1SEL AQ T1事件触发源选择
- T2SEL AQ T2事件触发源选择
- AQCTLB2(没用到,全部no action)
- T1U 增计数模式下事件触发T1的反应
- T1D 减计数模式下事件触发T1的反应
- T2U 增计数模式下事件触发T2的反应
- T2D 减计数模式下事件触发T2的反应
- AQCSFRC(没用到,全部no action)
- CSFA continuous software force on Output A的输出方式
- CSFB continuous software force on Output B的输出方式
- AQCTL
- DB模块
- DBCTL
- IN_MODE DB模块的两个输入源
- POLSEL DB模块的两个输出极性选择
- OUT_MODE DB模块的两个输出源
- SHDWDBREDMODE DB RED REG选择是否使用SHDW REG
- SHDWDBFEDMODE DB FED REG选择是否使用SHDW REG
- LOADREDMODE 选择load模式if选择了SHDW REG
- LOADFEDMODE 选择load模式if选择了SHDW REG
- OUTSWAP 选择输出A和B是否交换swap
- DEDB_MODE 选择输入是否要双边沿延迟
- HALFCYCLE 选择是否分半频
- DBRED rising edge delay value
- DBFED falling edge delay value
- DBCTL
- CMP模块
- CMPA 给数值
- CMPB 给数值
- TZ模块 (没用到,全部disable)
- TZSEL
- CBC1
- OSHT2
- OSHT3
- DCAEVT1
- DCAEVT2
- DCBEVT1
- DCBEVT2
- TZCTL
- TZA
- TZB
- DCAEVT1
- DCAEVT2
- DCBEVT1
- DCBEVT2
- TZEINT
- OST
- TZDCSEL
- DCAEVT1
- DCAEVT2
- DCBEVT1
- DCBEVT2
- TZSEL
- Clear 所有ISR 标志位(CNY=n就需要清理n+1次)
- ETCNTINITCTL
- INITINITRC 选择是否initialize EPWMxINT 2 计数器
- SOCAINITFRC 选择是否initialize EPWMxSOCA 2 计数器
- SOCBINITFRC 选择是否initialize EPWMxSOCB 2 计数器
- ETCLR 需要重复写n次
- ETCNTINITCTL
- ET模块
- ETSEL
- INTEN 使能中断enable interrupt
- INTSEL 选择中断触发条件TBCTR=
- SOCAEN 使能ADC开始转换EPWMxSOCA脉冲
- SOCASEL 选择EPWMxSOCA脉冲触发条件
- SOCBEN 使能ADC开始转换EPWMxSOCB脉冲
- SOCBSEL 选择EPWMxSOCB脉冲触发条件
- ETPS
- INTPRD 选择interrupt触发周期
- SOCAPRD 选择EPWMxSOCA触发周期
- SOCBPRD 选择EPWMxSOCB触发周期
- ETSEL
- DC模块(没用到)
- DCAHTRIPSEL
- TB模块
-
-
- DCALTRIPSEL
- DCBHTRIPSEL
- DCBLTRIPSEL
- DCTRIPSEL
- DCAHCOMPSEL
- DCALCOMPSEL
- DCBHCOMPSEL
- DCBLCOMPSEL
- DCACTL
- EVT1SRCSEL
- EVT1FRCSYNCSEL
- EVT1SOCE
- EVT1SYNCE
- EVT2SRCSEL
- EVT2FRCSYNCSEL
- DCBCTL
- EVT1SRCSEL
- EVT1FRCSYNCSEL
- EVT1SOCE
- EVT1SYNCE
- EVT2SRCSEL
- EVT2FRCSYNCSEL
- DCFCTL DC filter ctl
- DCCAPCTL DC capture ctl
- DCFOFFSET DC filter offset
- DCWINDOW DC filter window
-
7. EPWM模块代码学习(基于TMS320F28335)
- EALLOW、EDIS都是什么意思?为什么总感觉它们成对出现在代码中?
答:EALLOW(Edit allow)一般和 EDIS(Edit disable)配套使用。F28335中有一些配置寄存器是受保护的,无法直接操作。在对这些寄存器进行修改之前,需要先取电保护功能。EALLOW指令用于允许对寄存器进行操作,即解除寄存器保护功能。在操作之后,用EDIS指令恢复寄存器的被保护状态。
//代码/
EALLOW; //(Edit ALLOW),允许操作被保护的寄存器
EDIS; //(Edit disable), 禁止操作被保护的寄存器 | 开起写保护
//代码/
- Shadow影子寄存器
怎么理解它,不太恰当的比喻:古代皇帝阅读奏折,最底层九品芝麻官的奏折无法直接递上来给皇帝看的,大部分情况下,都是由丞相审理出来,先过一道手,再交给皇帝。Shadow跟这个有点类似,你不是要给我写东西吗?你先把数据先放到影子寄存器,到某一个时刻,我再从影子寄存器里面取走,拿到我真的用的地方去。那么好处是什么?在环路控制的时候,如果说环路输出值计算完了以后,要往这个寄存器里面装载,刚好这个周期,还没完,如果这时候你让它立即生效的话,就可能会导致环路震荡,你本周期正在执行的,应该是上周期计算出来的理论值,结果你把上一个周期计算的理论值打破了。也就是Shadow寄存器的好处是当我本周期结束的时候,才把计算出来的东西放在下个周期来用,这样来讲要稳定一些。
对于这个计数器,我们重点需要设置的点包括:
1 分频系数: 关系到计数步长,宏观上影响占空比/周期的最小刻度
2 计数方式: Up、Down、Up-Down,前面章节已经介绍过;
3 周期值: 直接影响开关频率
4 同步输入:直接影响周期/占空比
5 同步输出:影响其他 ePWM 模块
6 周期生效方式:在 PFM 场景下,影响环路的控制方式,(上面讲的影子寄存器相关)
十三、CPMSS
the Comparator Subsystem (CMPSS)由模拟比较器和相关支持电路组成。经常用于电源应用,例如峰值电流模控制、转换模控制、电源因素更正、电压保护控制等等。
比较器子系统是围绕多个模块构建的。每个子系统包含两个比较器,两个参考12位DAC和两个数字滤波器digital filters。该子系统还包括两个斜坡发生器ramp generators。
这个斜坡生成器上下倾斜。比较器在每个模块内表示为“H”或“L”,其中“H”和“L”分别代表高和低。每个比较器产生一个数字输出,指示是否正输入上的电压大于负输入上的电压。比较器的正输入由外部引脚驱动。负输入可以由外部引脚或可编程参考12位DAC驱动。每个比较器输出都通过一个可编程数字滤波器,该滤波器可以去除杂散跳闸信号。如果不需要过滤,也可以使用未过滤的输出。两个斜坡发生器电路可选地可用于控制子系统中的高和低比较器的参考12位DAC值。DAC与封装器一起可以用于生成斜坡,该斜坡用于峰值电流模式控制(PCMC)和其他应用中的斜坡补偿。该子系统还与EPWM一起工作,以支持二极管仿真模式。
CTRIPx(x=“H”或“L”)信号连接到ePWM x-BAR,用于ePWM跳闸响应
CTRIPxOUTx(x=“H”或“L”)信号连接到输出x-BAR,用于外部信号。
1. 比较器
正极A大于负极B输出高电平1,反之输出低电平0。
比较器子模块
输入:
- "+": 输入由“CMPx_HP外部信号”输入
- "-": 输入由COMP[COMPSOURCE]信号决定输入源是“内部12-bit DAC输入”还是“CMPx_NH”。
输出:
- 先不管第一个MUX(我也不知道为什么,还没用上)。
- 输出经过”COMPCTL[COPMHINV]信号”决定是否翻转后输出到下一步(可以不经过数字滤波直接异步输出、经过滤波输出、锁存输出)。
配置COMPCTL:
- COMPHSOURCE比较器输入源: 0:输入由内部DAC驱动; 1:输入外部引脚。
- COMPHINV输出转换:0输出原值,1输出相反数。
- ASYNCHEN比较器异步通道使能:如果后面滤波输出选择锁存可使能异步输出给OR门。
2. 参考DAC
每个12bit的参考DAC能驱动参考电压到各自的阴极输入CMP(1.比较器的输入)。12bit参考比较器只输出到内部,不会到外边。
对于每个参考12位DAC,存在两组DACxVAL寄存器,即DACxVALA和DACxVALS。
- DACxVALA是一个只读寄存器,它主动控制参考12位DAC值。
- DACxVALS是一个可写的影子寄存器,它可以立即加载到DACxVAL中,也可以与下一个EPWMSYNCPER同步加载事件。H和L参考12位DAC(DACx)可以可选地从斜坡生成器Ramp Generator或者通过寄存器DACxVALS来获取寄存器DACxVALA值。
参考12位DAC的工作范围由上限DACREF和下限VSSA限定。默认情况下,高压基准由”COMPDACxCTL[SELREF]信号“默认为VDDA,也可以配置为VDAC。DACH设置必须始终高于DACL设置。如果用户未使用DACL,则DACLVALS寄存器必须设置为0,以避免比较器COMPL跳闸trip并影响DACH。在这种情况下,DACHVALS设置没有限制。当不使用DACH时,用户必须将DACHVALS寄存器设置为最大值。
输出 (为什么+1呢?)
输入
- 由"COMPDACxCTL[DACSOURCE]信号"选择DAC的信号源来自”内部DACxVALS“还是”RampGenerator“。
输出
- 输出到”DACxVALA“中,可以传递到比较器作为负极输入。
配置COMPDACHCTL:
- DACSOURECE:决定DAC输入源。0:DACHVALS. 1: H斜坡发生器。
- RAMPSOURCE: 斜坡发生器输入源,选择下列n个中的一个EPWMnSYNCPER信号。
- RAMPLOADSEL:(ramp generator)当COMPSTS被触发时,选择装载源到RAMPSTS里。0: RAMPHREFA。 1:RAMPHREFS。
- SELREF:决定DAC的参考电压。 0:VDDA. 1: VDAC.
- SWLOADSEL: software选择DACHVALS的输入触发条件。 0:SYSCLK. 1: EPWMSYNCPER.
- BLACKEN: EPWMBLANK使能。 0:不用 1:用
- BLANKSOURCE: 决定用哪一个EPWMnBLANK。
- FREESOFT: 选择模拟暂停模式:自由运行/software模拟。 00b:立即停止。01b:完成此次斜坡直到下一个EPWMSYNCPER到来时停止。1Xb:自由运行。
3. 斜坡发生器
(没用过,没有很理解,只是略微了解一下技术手册上的内容)
产生上升/下降斜坡给12bit ref DAC 的H或L输入。
在此模式中, RAMPSTS倒计数寄存器的最高有效12位作为12bit REF DA的输入。RAMPSTS倒计时寄存器的低4位有效地用作可通过RAMPxSTEPVALA配置的下降或上升斜坡速率的预刻度。
斜坡发生器Ramp Generator由DACSOURCE=1信号使能,此时RAMPSTS的值由RAMPxREFS装载并保持不变直到收到TRIGSYNC信号。在接收到所选择的TRIGSYNC信号之后,在每个后续的SYSCLK周期上从RAMPSTS中减去RAMPxSTEPVALA的值。
为了防止减法在TRIGSYNC事件之后开始SYSCLK周期,可用作延迟计数器的RAMPDLYA寄存器来保持RAMPSTS减法或加法。在接收到TRIGSYNC事件时,RAMPDLYA的值在每个SYSCLK周期递减一,直到寄存器达到零。因此,只有当RAMPDLYA为零时,RAMPSTS减法才开始。类似地,在递增模式(RAMPDIR=1)中,RAMPSTS相加仅在RAMPDLYA为零时开始。(看不懂思密达)
此外,如果RAMPSTS的值达到零并且斜坡发生器处于递减模式(RAMPDIR=0),RAMPSTS寄存器保持静止在零,直到接收到下一个TRIGSYNC。如果坡道生成器处于递增模式(RAMPDIR=1),并且RAMPSTS的值达到0xFFFF,则RAMPSTS寄存器值保持在该值,直到接收到下一个TRIGSYNC为止。
由于斜坡发生器在TRIGSYNC和COMPHSTS的每个上升沿上进行状态改变当这两个事件同时发生或非常接近时,可以在实例上预期以下行为在一起:
- 情况1:COMPHSTS上升沿发生在TRIGSYNC上升沿之前的一个或多个周期。RAMPSTS在COMPHSTS上升沿事件时停止递减。RAMPSTS开始递减RAMPDLYA达到0时的TRIGSYNC上升沿事件。
- 情况2:COMPHSTS上升沿与TRIGSYNC上升沿同时发生。EPWMSYNCPER上升沿事件优先,RAMPDLYA时RAMPSTS开始递减达到0。COMPHSTS上升沿事件被忽略,并且不会停止RAMPSTS。
- 情况3:COMPHSTS上升沿发生在TRIGSYNC上升沿之后但RAMPDLYA之前的一个或多个周期达到0。当RAMPDLYA达到0时,RAMPSTS不递减。
- 情况4:当RAMPDLYA从TRIGSYNC上升沿达到0时,COMPHSTS上升沿同时发生。RAMPSTS不递减。
4. 数字滤波
(需要初始化)
数字滤波器在从输入端获取的FIFO样本(SAMPWIN)窗口上工作。滤波器输出解析为采样窗口的多数值majority,其中多数由阈值(THRESH)值定义。如果不满足多数阈值,则滤波器输出保持不变。
为了正确操作,THRESH的值必须大于SAMPWIN/2且小于或等于SAMPWIN。
预缩放函数(CLKPRESCALE)确定滤波器采样率,其中滤波器FIFO在每个CLKPRESCALE捕获一个样本。FIFO中的旧数据将被丢弃。
请注意,对于SAMPWIN、THRESH和CLKPRESCALE,数字滤波器使用的内部数字在所有情况下都是+1。
本质上,samples=SAMPWIN+1,threshold=THRESH+1,prescale=CLKPRESCALE+1。
采样窗口:9个数(实际会多取一个)
输出=阈值数(采样窗口中的众数):至少超过一半且不超过窗口数
预采样:采样率=clkprescale+1,每取一次新的就会舍去旧的
配置filter:
CTRIPLFILCLK: CTRIPL Filter Clock Control Register采样时钟预分频=CLKPRESCALE+1.
CTRIPLFILCYL:
- SAMPWIN: sample window size采样窗口大小,一般设置为SAMPWIN+
- THRESH: 众数阈值。一般设置为THRESH+1.
FILINIT: 初始化。 0:无效果。 1:将所有sample初始化到filter输入值。
输出可能会经过滤波也可能不经过,配置输出:
COMPCTL:
- CTRIPnSEL输出到EPWM X-BAR:选择TRIP输出源。 0异步不经过滤波 1同步不经过滤波 2滤波后 3滤波后锁存输出
- CTRIPOUTnSEL输出到OUTPUT X-BAR: 同上。
COMHYSCTL: 比较器迟滞。设置比较器输入上的滞后量。
COMPSTSCLR: nLATCHCLR清除software锁存。 0无效果,1生成锁存复位信号的单个脉冲
COMPCTL: COMPDACE使能DAC
5. 配置CMPSS
- Check所有CMP是否完成配置。已完成则return
- 检查DAC数值是否超过最大值4096,并且设置到寄存器中
- 配置比较器(所有的都要H+L)
- COMPDACE取消使能COPM
- Comp CTL
- COMPxSOURCE = 0 选择比较器的N端输入
- COMPxINV = 选择比较器的输出是否翻转
- ASYNCEN 选择比较器的输出是否使能为锁存异步输出
- 配置DAC(所有的都要H+L)
- DACSOURCE 选择DACxVALA的输入由DACxVALS输出还是Ramp Generator输出
- RAMPSOURCE 选择RG的输入EPWMnSYNCPER
- RAMPLOADSEL 选择RG的COPMxSTS的输入是RAMPxREFA还是RAMPxREFS
- SELREF 选择DAC的参考电压源(最大值)是VDDA还是VDAC。
- SWLOADSEL 选择当DAC的输入源是DACxVALS时的时钟时SYSCLK还是EPWMSYNCPER
- BLANKEN 选择是否使能EPWMBALCNK
- BLANKSOURCE 选择输入源是EPWMnBLANK
- FREESOFT 选择当模拟暂停时的RG行为是立即执行还是等待下一个EPWMSYNCPER来临还是都不管
- 配置digital filter(所有的都要H+L)
- CTRIPxFILCLKCTL 滤波时钟预分频
- SAMPWIN 设置采样窗口大小+1
- THRESH 设置众数+1
- FILINIT 选择是否将所有samples设置成输入值
- 配置输出(所有的都要H+L)
- CTRIPxSEL 配置输出到EPWM X-BAR
- CTRIPOUTSEL配置输出到OUTPUT X-BAR
- CMPHYS配置输出迟滞倍数
- 清除锁存(所有的都要H+L)
- xLATCHCLR 是否清除锁存
- 使能COMP (3.a步骤取消使能,这一步再打开)
- 输入数值
十四、UART
Universal asynchronous receiver/transmitter
功能:并行-串行和串行-并行转换。
特征:
- 波特率:常速(/16)12.5Mbps,高速(/8)25Mbps
- 16-deep 8-bit的TX和RX FIFOs
描述:
-
- TX和RX
发送Tx执行的是并行-串行转换,输出串行比特流数据。
数据组成:起始位+数据位(LSB-MSB)+奇偶校验位+结束位。
接收Rx对接收到的比特流执行串并转换。
还执行溢出、奇偶校验、帧错误检查和断线检测,并且它们的状态伴随着写入接收FIFO的数据。
-
- 波特率生成器
Baud-rate divisor是由16位整数Integer和6位小数部分Fraction组成的22位数字。
这两个值形成的值来确定比特周期。16位整数UARTIBRD寄存器和6位分数部分UARTFBRD寄存器。
波特率除数(BRD)与系统时钟具有以下关系(其中BRDI是BRD的整数部分,BRDF是小数部分,用小数点分隔。)
高速模式CLKDiv=8,正常模式ClkkDiv=16.这个模式有UARTCTL.HSE位决定。
小数部分的计算:+0.5是为了补偿误差(四舍五入)。
-
- 数据传输
R数据和T数据都储存在16-byte的FIFOs里,R数据FIFO额外有4bits的状态位。
T:数据先存在FIFO里,当数据准备从FIFO往UART开始传输时,UART enable=1且busy=1,此时FIFO非空信号保持=1直到FIFO数据传输完毕=0,。传输完毕后,FIFO空信号=1,非空信号=0,busy=0,uart enable=0.
R:当receiver空闲(UnRx=1),data输入=0(检测到start bit)时,接收计数器开始计数直到数据采样八个周期(Baud16)/四个周期(Baud8)。仅采样周期后UnRx=0判断起始位有效,否则忽略此次起始位。起始位有效后开始接收相应字长的数据位(字长可选UARTLCRH.WLEN.),奇偶校验位(可选),结束位(UnRx=1)。如果没有结束位,R FIFO依旧持续接收存储错误数据直到接收完相应字长位,此时称作成帧错误framing error。
-
- Serial IR ( SIR )
没用过。
-
- 9-bit UART模式
没用过。
-
- FIFO
UART有两个 16-deep 8-bit wide FIFO,一个用于接收一个用于发送,用UARTDR寄存器。发送模式给8bit数据到T FIFO,接收模式写入12bit(8bit数据+4bit error flag)到UARTDR里。FIFO状态由UART FLAG和UART Receive Status’两个寄存器决定,前者判断空满信号(满FE/非空FF),后者用UARTRSR.OE判断是否overrun。如果没使用FIFO模式时,FIFO作为1 btye-deep的保持寄存器(开了是16,没开是1)。
FIFO产生中断的触发点由UART interrupt FIFO level select(UARTIFLS)寄存器。两个FIFO都可以单独配置为触发不同级别的中断。可用配置包括¼、¼、½、¾和⏴。例如,如果选择¼选项进行接收FIFO,UART在接收到四个数据字节后产生接收中断。未复位,两个FIFO均为被配置为在½标记处触发中断。
-
- 中断
没用过。
-
- Loopback operation回环模式
当UART enable=1且UARTCTL.LBE=1时开启回环模式,此时用于诊断/调试工作,UnTx的输出接到UnRx的输入接收。
-
- DMA operation
没用过。
使用UART之前需要先关闭,初始化后再打开:
-
-
-
- 关闭UART使能:UARTCTL.UARTEN=0;
- 写入波特率:整数UARTIBRD.BRD,小数UARTFBRD.BRD。
- 写入相关参数配置:UARTLCRH
- 如果选择DMA通道:UARTDMACTL
- 打开UART使能:UARTCTL.UARTEN=1;
-
-
- 例程2(loopback)
初始化(时钟、uart外设)、初始化GPIO(关闭引脚lock,使能内部pull-up)
- 例程4(FIFO+DMA)
建议使用FIFO(实际我只用了FIFO,没用DMA)。
BUFFER_SIZE:接收/发送FIFO之间传输的数据位数,必须是能被UART_BUFFER_SIZE整除的偶数。
UART_BUFFER_SIZE :
问题:
-
-
-
- 突然烧录不了工程?
-
-
图:烧录失败报错原因
C28XX板子有两个CPU,当两个都被占用时无法继续烧录。问题产生的原因可能是之前烧录时配置了两个CPU。解决方法是烧录时只使用一个CPU,如图所示。或者在工程路径下(例如:D:\myccs\MY_F28P65_App_V1002_slave\MY_F28P65_App_V1002_slave\Project)删除.lauches文件夹后重新烧录。
图:烧录配置示意图
单片机开发
通信开发层级:硬件-->驱动层-->接口层-->协议层-->应用
驱动层:直接与硬件打交道的一层,它为操作系统和应用提供硬件驱动或底层核心支持。在嵌入式系统中,驱动程序有时也称为板级支持包(BSP)。BSP具有在嵌入式系统上电后初始化系统的基本硬件环境的功能,基本硬件包括微处理器、存储器、中断控制器、DMA、定时器等。驱动层--般可以有三种类型的程序,即板级初始化程序、标准驱动程序和应用驱动程序。
十五、SCI
- SCI学习
-
- A
- B
- SCI配置
- SCI验证
- 示波器使用
- 示波器配件
- 示波器使用
电源线(剪掉地线)一根、探头一根(衰减开关:1X)、杜邦线。
-
-
- 设置
- 此时只用了探头1,设置探头的衰减比率为00:1。
- 触发方式:normal触发、触发源1、斜率下降沿
- 运行模式:单次采集Single
- 设置
- 配置开发板
-
软件:CCS
开发板:F28P65X
Project:
发送Tx:在sciasend函数中持续赋值。编译后,用示波器的单次采集观测是否有输出。此时只有粗略观测,有波形输出即可,不观测是否是正确对应的数值波形。
接收Rx:需要两块开发板一个发送数据一个接收数据。也可用串口助手代替发送数据的开发板。发送板T引脚接接收板R引脚,两个板的GND相接。发送板的程序需要重新上电也能运行。观测接收程序的SciaReceive函数的rxBuff寄存器是否接收到正确的值。
-
- Debug
- 发送Tx
- Debug
示波器是否接受到数据。
开发板引脚是否正确接入。
程序GPIO口是否正确配置成SCI外设。
SCI是否正常工作/初始化。
SCI程序是否正常发送数据。
问题:
- 程序正常、配置正常但是观测不到发送数据。
问题来源:1. 开发板引脚跳线帽没有选择输出。2. 示波器不会用。
解决办法:1. 选择相应的输出。 2. 用单次采集模式放大观测波形。
反思:不会就学吧。开发板U6芯片选择GPIO42/43的输出口,用小镊子拨动开关SEL1=1时输出到BP的J1-4/5引脚,可以连接示波器观测波形。因为发送板设置的不间断发送数据,使用连续运行模式(同一数据的多次采集)很难观测,所以需要放大观测单步事件(不会出现覆盖显示的波形数据)。
还是不会用示波器!!!
(发送板能用示波器观测到发送的数据,但是接收板不能看到,不知道为什么)
-
-
- 接收Rx
-
观测rxBuff寄存器是否有输入且正确。
问题:没有接受到数据
问题来源:开发板引脚跳线帽没有选择输出。
解决办法:选择输出。
十六、GPIO
- GPIO学习
GPIO模块控制着设备数字复用digital multiplexing,使用共享引脚来最大化应用灵活性。引脚名字一般为GPIO0、GPIO1……。引脚可以独立作为数字输入输出I/O口使用,也可以被连接到外设的I/O信号上。输入信号可以用于去除不想要的噪声。
有8个I/O端
- IO验证
- 示波器使用
- 示波器配件
- 示波器使用
电源线(剪掉地线)一根、探头一根(衰减开关:1X)、杜邦线。
-
-
- 设置
- 此时只用了探头1,设置探头的衰减比率为00:1。
- 触发方式:边沿触发、触发源1、斜率上升沿
- 运行模式:实时采集用RUN/STOP(单次采集用Single)
- 设置
- 配置开发板
-
软件:CCS
开发板:F28P65X
Project:
编译后,用相应的数据寄存器GpioDataRegs.GPyDAT.GPIOxx写值观测示波器验证输出OUT,给开发板相应输入引脚GPIOxx接入开发板3v3或者gnd观测对应数据寄存器GpioDataRegs.GPyDAT.GPIOxx变化验证输入INPUT。
-
- Debug
- 输出OUTPUT
- Debug
看连接到示波器的开发板引脚是否接错。
看GPIO配置的功能寄存器GPyMUX和GPyGMUX是否正确。
要确保配置的和实际输出的是匹配的!!
出现过的问题
-
-
-
- 程序配置正确但是无法改写数据寄存器。
-
-
问题来源:程序中有其他地方调用此寄存器导致无法写值。
解决方法:暂时注释掉其他调用。
-
-
-
- 程序配置正确但是示波器无显示
-
-
问题来源:开发板引脚接错。
解决办法:接正确的引脚。
反思:出现问题的时候可以逆向思维找根据,排除所有不可能之后,剩下的一定是结果。找到根源后修改就很简单,困难点在于找根源。问题1出现的原因在于我根本没想到过其他地方还可能会用到这个寄存器,如果一个寄存器不可用一定是被别的地方占用了。找函数时,用search 非常精准快速。还是经验少,做多了这个问题应该很好解决。问题2出现的原因在于想当然了。之前接引脚基本都是从下往上数,比如说73是从下往上数第3个。这次的部分引脚是从上往下数,所以就接错了。这个问题2还是很好解决的,就是太粗心了。
-
-
- 输入INPUT
-
看开发板引脚是否接错。
看程序里相关配置是否出错。
问题: 没有出现问题。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ji-chu/105424.html