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.