中断
这是一个Cpu_timer_0的中断
void init_xint1(void)
{
EALLOW; // This is needed to write to EALLOW protected registers
PieVectTable.TINT0 = &cpu_timer0_isr; // Enable CPU INT1 which is connected to CPU-Timer 0
IER |= M_INT1; // Enable TINT0 in the PIE: Group 1 interrupt 7
PieCtrlRegs.PIEIER1.bit.INTx7 = 1; // Enable INT1.7 TINT0
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM
EDIS;
}
_interrupt void cpu_timer0_isr(void){
<这里写CPU相应Cpu_timer_0中断执行的程序>
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; //注意执行完该中断后手动复位Acknowledge位,以使其他中断能够通过。
}
让中断通过:打开中断从外设到Core的各个屏障
3级:CPU, PIE, Peripheral
CPU 12个中断 ,有使能位和标志位,使能位通过操作IER |= M_INTx 改变,这个语句代表了使能M |= M_INTx
PIE 8个子中断,有使能位和标志位,使能位通过操作这个寄存器来实现:PieCtrlRegs.PIEIER1.bit.INTx7 = 1
Peripheral 就是有些外设比较高级,自己提供了控制是否输出中断的使能控制信号。这个CPU_timer0就没有单独设置控制自己使能与否的控制信号。
有了中断执行什么?
通过操作PieVectTable这个结构体中存贮了所有中断执行的程序是什么,那么便有一个问题:怎么确定要执行的程序是什么呀?通过把中断程序的入口地址存到向量表中。那么问题又来了:入口地址是啥
呀?其实就是 &<程序的名字>
解释下上面的例子:
中断后执行的程序是这个:
_interrupt void cpu_timer0_isr(void){
<这里写CPU相应Cpu_timer_0中断执行的程序>
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; //注意执行完该中断后手动复位Acknowledge位,以使其他中断能够通过。
}
入口地址就这么表示
&_interrupt void cpu_timer0_isr
SPI 通信
几个寄存器
- 缓冲寄存器(缓冲器)
发送缓冲寄存器内存储下一个要发送的字符;接收缓冲寄存器存储下一个接收到的位; - 数据寄存器
这个寄存器比较有趣,本身是一个移位寄存器,那么同时有输入和输出,所以这个是双线通信,无论主机还是从机,时时刻刻都在发送和接收。
操作模式
插播一条基础概念:数据对齐,一张图解决一切。
右对齐right-justified
左对齐left-justified
SPIBBR决定传输速率。
主从工作模式
发送:将数据写在DAT寄存器中,最高位往外出。
接收:将数据写在DAT寄存器中,最低位往里面写。
所以读写使用的是同一个DAT寄存器,周而复始,生生不息。
前方有坑!!!注意
就因为发送数据是从DAT的MSB发出,接收是DAT的LSB接收,DAT是16位长的,那么如果你发送的数据的二进制形式不够16位长就要向左移位!!
eg.
xxxx xxxx xxxx xxxx // 我是SpiaRegs.SPIDAT,16位长
// 假设我定义了一个字符 uint8_t char;
uint8_t char;
char='a';
那么发送的时候,通过配置SPICCR.
一条注意:SPICLK的输入必须
CCS数据类型
uint<数字>_t
<数字>代表的这个数据类型所占的内存长度。
字符char 占一个字节,<数字>=8, uint8_t
整数int 占4个字节,<数字>=48=32。 uint16_t
短整形 short int占2个字节 <数字>=28=16 uint32_t
长整型 long int 占8个字节 <数字>=8*8=64 uint64_t
整型:
整型在内存中就是以2进制存储,所以寄存器中的数值就是整型对应的二进制值。
运算符
1111<<2 = 1100
1111 >>2 = 0011
存储的二进制数序列左移或右移,溢出的数值舍弃,空缺的数值补零。
0000 |= 1100
result: 1100
1010 |= 1100
result: 1110
老大给任务了,SPIA搞个无线通信
按照进度和问题来展开,进行的计划安排:
血的教训
学习DSP一定先搞懂基本原理,然后看带着目标去看datasheet的结构图(注意图中的寄存器)和数据流流向,然后看例程来搞懂配置寄存器的顺序。
Come on!
- 时钟的频率初始化在哪里,初始化的频率是多少?
1.1 时钟的初始化在InitSysCtrl()中其中InitPLL(div,divsel)设置了OSCCLK到SYSCLKOUT的关系;其中InitPeripheralClocks()设置了,外设SYSCLKOUT到外设低速时钟LOSPCP的关系。
1.2 SYSCLK = 60MHz ,外设时钟LOSPCP = SYSCLK / 4 = 15MHz - 设置好了时钟,SPIA怎么初始化?(怎么使能,所使用的GPIO引脚,波特率,主从模式,时钟沿极性和相位,初始化设置FIFO),发送数据怎么发,怎么看接收的数据。
2.1 例程中先设置了GPIO的复用
2.2 SPIA直接进入FIFO的初始化,里面调用了SPI的初始化程序
void
spi_fifo_init()
{
//
// Initialize SPI FIFO registers
//
SpiaRegs.SPIFFTX.all=0xC022; // Enable FIFO's, set TX FIFO level to 2,使能中断
SpiaRegs.SPIFFRX.all=0x0022; // Set RX FIFO level to 2,使能中断
SpiaRegs.SPIFFCT.all=0x00; // FIFO发送缓冲器到移位寄存器之间的延迟为0
SpiaRegs.SPIFFTX.bit.TXFIFO=1; //使能发送FIFO
SpiaRegs.SPIFFRX.bit.RXFIFORESET=1; //使能发送FIFO
//
// Initialize core SPI registers
//
InitSpi();
}
SPI的初始化程序
2.2 SPIA属于外设,所有的外设都需要主动使能才能使用。
- 怎么发送数据?
写数据的时候遇到了问题:怎么写一个二进制常量到寄存器中呢?C中没有二进制表示常数的形式,只有8进制0开头 eg. 0100 这是八进制 = 18^2 + 08 +0 =64; 和16进制 0x????所以写寄存器的方法是转换成16进制或者8进制,eg.要写二进制的0001就这么写:
xxxxRegs.bit.Div = 0x1;
简单做法,以16位为例来发送,然后接收到的数据进行移位。
无线射频模块AS01-ML01DP5学习记录
第一遍读数据手册
有用的参数:
1.9-3.6V DC供电
5V tolerant input
读datasheet
Pin Function
CE: 数字信号输入,使能RX/TX mode
CSN: 片选端
SCK: 时钟
IRQ: 可屏蔽中断引脚Limiting values 限制值,超了就烧
-
配置方法
这个设备非常优秀,写成了杂乱的状态机模式。
工作模式
CE维持高电平10us
核心:data and control interface
注意:这个是8bit的指令集command set
3级FIFO
10Mbps SPI
有个问题:所有的控制都是有上电之后的寄存器内数值决定的,怎么修改寄存器的数值?
- 搞清楚原理
- 想法子让SPI实现
! 原理原理原理
SPI
有几点注意
注意1:命令是1字节,MSB->LSB
注意2:Data bytes:可能是多个字节,写在地址位的后面。
写在寄存器P52上:
读寄存器的command
控制位1 byte:000<五位寄存器地址>
写寄存器的command
控制位1 byte:001<五位寄存器地址>
P57 Register Map上面写有寄存器的地址。尽管是Hex 2位数,但是二进制前三位都是0,所以实际上就是5位二进制数字即可。
然后根据http://www.ebyte.com/new-view-info.aspx?id=201网址中的固件编程思路来进行配置外设的寄存器即可。
内容在表格中。
配置方法:
- Select RX by setting the PRIM_RX bit in the CONFIG register to high. All data pipes that receive
data must be enabled (EN_RXADDR register), enable auto acknowledgement for all pipes running
Enhanced ShockBurst™ (EN_AA register), and set the correct payload widths (RX_PW_Px registers). Set up addresses as described in item 2 in the Enhanced ShockBurst™ transmitting payload example above. - Start Active RX mode by setting CE high.
- After 130µs nRF24L01+ monitors the air for incoming communication.
- When a valid packet is received (matching address and correct CRC), the payload is stored in the
RX-FIFO, and the RX_DR bit in STATUS register is set high. The IRQ pin is active when RX_DR is
high. RX_P_NO in STATUS register indicates what data pipe the payload has been received in. - If auto acknowledgement is enabled, an ACK packet is transmitted back, unless the NO_ACK bit
is set in the received packet. If there is a payload in the TX_PLD FIFO, this payload is added to
the ACK packet. - MCU sets the CE pin low to enter standby-I mode (low current mode).
- MCU can clock out the payload data at a suitable rate through the SPI.
- nRF24L01+ is now ready for entering TX or RX mode or power down mode