SGPIO就是串行GPIO的意思,这里的串行GPIO跟Intel的SGPIO是两码事,Intel的SGPIO顶多叫USCI(通用串行通信外设),这个SGPIO就是真的串行,下面用最简单的PWM发生来说.
首先只能做很简单分辨率的PWM,SGPIO也是有个输入时钟的,这个可以定性认为是整个频率,即.

把这一段定量分成32份.

因为SGPIO是移位匹配寄存器(我发明的名词)

比如我设置成0x00000001,那么就是0位置是1,匹配到0位置是1,那么DOUT为1,其他位置是0,所以DOUT是0,假设我们寄存器是0xAAAAAAAA,那么就是移到BIT0的时候0,然后BIT1被拉1.
我现在取值是0x00000001.注意红框位置.

#include "LPC43xx.h"
/* Variables ------------------------------------------------------------------*/
uint8_t chan = 0; //Variable used to get settings from the SGPIOPWMValue to the interrupt handler
uint8_t val = 0; //Variable used to get settings from the SGPIOPWMValue to the interrupt handler
uint8_t intcount = 0; //Variable used to count how many times REG_SS was updated
uint32_t PWMValues[0x21] = //All the 33 PWM values used for PWM
{
0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000F,
0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF, 0x000001FF,
0x000003FF, 0x000007FF, 0x00000FFF, 0x00001FFF, 0x00003FFF,
0x00007FFF, 0x0000FFFF, 0x0001FFFF, 0x0003FFFF, 0x0007FFFF,
0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 0x00FFFFFF,
0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF, 0x1FFFFFFF,
0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF
};
/*********************************************************************//**
* @brief Change PWM value of an SGPIO pin
* @param[in] value Should be between 0 and 33, 0 is off, 33 is on, 16 is ~50% PWM
* @param[in] channel SGPIO channel that should be changed
* @return None
**********************************************************************/
void SGPIOPWMValue(uint8_t value, uint8_t channel)
{
chan = channel; //Put the values into globab variables so the interrupt handler can reach it
val = value;
LPC_SGPIO->CLR_STATUS_1 = 0xFFFF; //Clear the interrupts
LPC_SGPIO->SET_EN_1 = 0x8000; //interrupt when slice 15 switches data register
}
void SGPIOPWMchaninit(uint32_t freq, uint8_t channel)
{
//Calculate the correct divider setting
uint32_t calceddivider = 0; //Variable to calculate the PWM frequency
calceddivider = 204000000;
calceddivider = (calceddivider / freq) - 1;
calceddivider = calceddivider / 0x20;
//Setup an SGPIO channel for PWM
LPC_SGPIO->OUT_MUX_CFG[channel] = 0x00000000; //one bit mode
LPC_SGPIO->SGPIO_MUX_CFG[channel] = (0x1 << 11); //internal clock, concave on
LPC_SGPIO->SLICE_MUX_CFG[channel] = 0x0; //Interrupt on match on
LPC_SGPIO->PRESET[channel] = calceddivider; //clock speed = ((supplied clock / 2) / (preset + 1))
LPC_SGPIO->COUNT[channel] = 0x0;
LPC_SGPIO->POS[channel] = 0x1F00; //after 32 clocks, switch data registers,
LPC_SGPIO->REG[channel] = 0xFFFFF; //Data in normal register, not important for now
LPC_SGPIO->REG_SS[channel] = 0xFFFFF; //Data in shadow register, used for match
}
void SGPIOPWMinit(void)
{
LPC_SGPIO->CLR_EN_0 = 0xffff; // disable interrupting on clock
LPC_SGPIO->CLR_EN_1 = 0xffff; // disable interrupting on clock
LPC_SGPIO->CLR_EN_2 = 0xffff; // disable interrupting on clock
LPC_SGPIO->CLR_EN_3 = 0xffff; // disable interrupting on clock
LPC_SGPIO->GPIO_OENREG = 0xFFFF; //All SGPIO's as output
LPC_SGPIO->CTRL_ENABLE = 0xFFFF; //Enable all SGPIO clocks.
NVIC_EnableIRQ(SGPIO_IRQn); //Enable SGPIO Interrupt
}
void SGPIO_IRQHandler (void) //Handles all SGPIO interrupts
{
uint32_t interruptvar = 0; //Variable used to store the interrupt value, what slice had an interrupt.
interruptvar = LPC_SGPIO->STATUS_1;
if (interruptvar & (1 << chan)) //Check if the correct channel got an data swap interrupt
{
LPC_SGPIO->REG_SS[chan] = PWMValues[val]; //Place the new value in the REG_SS rgister
intcount += 1; //Add one to the counter
LPC_SGPIO->CLR_STATUS_1 = 0xFFFF; //Clear the interrupts
if(intcount >= 2) //When the counter is 2 the REG_SS register has been updated twice
{
LPC_SGPIO->SET_EN_1 = 0x0000; //Stop the interrupts
LPC_SGPIO->CLR_EN_1 = 0xffff; //And clear the interrupt
intcount = 0; //Clear the counter
}
}
}
uint8_t SGPIOPWMstatus(void)
{
return intcount;
}
int main(void)
{
LPC_SCU->SFSP1_1 = 0x03; /* 关闭上拉 + FUNC3 */
SGPIOPWMinit();
SGPIOPWMchaninit(100000, 1);
SGPIOPWMValue(0x01, 1);
while (1)
{
}
}
所以生成的波形,就如最初的截图一样,我改成0xAAAAAAAA大家看看.

可见,匹配到就会显示电平,所以,这是一个PWM Val从0~32可调的PWM,算是准5Bit PWM了.他就是一个路过,检测到1还是0,就会发送.这让我想起了单线SPI(只有MOSI,又是我发明新名词了.),调制MOSI数据到32Bit,然后他自己发出去,然后其他几个SGPIO发送SCLK.当然DIN也是存入REG的.也就是两个SGPIO互相独立(软件上),工作上却看起来协作.
遗留问题:
- SGPIO SLICE,决定IO怎么排布.
- SGPIO 非1Bit Mode.是不是可以模拟QSPI.