我的问题是LM8330的PWM0的功能。
我正在为我们的一款产品开发一个5x10键盘驱动程序,它基于lm8330组件,使用来发出事件信号,KPY11列上的中断在矩阵中没有使用。
此外,我需要在其他KPY10列上使用PWM0,键盘也不使用PWM0,用于蜂鸣器或背光调节。
键盘工作正常,而PWM0只是不想工作。
我附加了用于初始化lm8330组件的源代码。 我想澄清的是,我在论坛上发现了我感兴趣的任何话题,但这还不足以使我的问题得到理解。
在论坛上,我还发现在编写PWM脚本的字模式的方法上有许多不准确之处。 有时,写入顺序报告为第一个LSB,然后是MSB,有时报告为第一个MSB,然后是LSB。
我认为它应该是MSB,然后是LSB,连续写入。 至少我希望。
在所附的源代码中有3个脚本,但没有任何脚本(如注释中所示)按预期工作。
我绝望了,因为我在各种组合中进行了无休止的测试,但没有任何积极的结果。
只有一件事需要报告,在键盘上。 我不得不重复命令“CLKMODE”来设置“操作模式”,否则键盘不工作,就好像在键盘编程中有一些指令一样,将其置于睡眠模式。
感谢那些能帮我的人。
#define LM8330_CMD_SET_KBDSETTLE 0x01 /* Set KBDSETTLE time. Initial time for keys to settle, before the key-scan process is started*/ #define LM8330_CMD_SET_KBDBOUNCE 0x02 /* Set debouncing time. */ #define LM8330_CMD_SET_KBDSIZE 0x03 /* Set keypad size. Defines the physical keyboard matrix size*/ #define LM8330_CMD_SET_KBDDEDCFG 0x04 /* Set Dedicated Key Register. Defines if a key is used as a standard keyboard/GPIO pin or whether it is used as dedicated key input*/ #define LM8330_CMD_SET_KBDDEDCFG0 0x04 /* Set Dedicated Key Register. Defines if a key is used as a standard keyboard/GPIO pin or whether it is used as dedicated key input*/ #define LM8330_CMD_SET_KBDDEDCFG1 0x05 /* Set Dedicated Key Register. Defines if a key is used as a standard keyboard/GPIO pin or whether it is used as dedicated key input*/ #define LM8330_CMD_READ_KBDRIS 0x06 /* Get Keyboard Raw Interrupt Status register. Returns the status of stored keyboard interrupts*/ #define LM8330_CMD_READ_KINT 0x06 #define LM8330_CMD_READ_KBDMIS 0x07 /* Get Keypad Masked Interrupt Status Register. Returns the status on masked keyboard interrupts after masking with the KBDMSK register*/ #define LM8330_CMD_SET_KBDIC 0x08 /* Set Keypad Interrupt Clear Register. Setting these bits clears Keypad active Interrupts */ #define LM8330_CMD_SET_KBDMSK 0x09 /* Set Keypad Interrupt Mask Register. Configures masking of keyboard interrupts. Masked interrupts do not trigger an event on the Interrupt output */ #define LM8330_CMD_READ_KBDCODE0 0x0B /* Read the first detected key. */ #define LM8330_CMD_READ_KBDCODE1 0x0C /* Read the second detected key. */ #define LM8330_CMD_READ_KBDCODE2 0x0D /* Read the third detected key. */ #define LM8330_CMD_READ_KBDCODE3 0x0E /* Read the forth detected key. */ #define LM8330_CMD_READ_EVTCODE 0x10 /* KRead key Event from Code Register */ #define LM8330_CMD_SET_TIMCFG0 0x60 /* Set PWM Timer 0 Configuration Register. This register configures interrupt masking of the associated PWM channel*/ #define LM8330_CMD_SET_PWMCFG0 0x61 /* Set PWM Timer 0 Conf iguration Control Register. This register defines interrupt masking and the output behavior for the associated PWM channel */ #define LM8330_CMD_SET_PWMCFG1 0x69 /* Set PWM Timer 1 Conf iguration Control Register. This register defines interrupt masking and the output behavior for the associated PWM channel */ #define LM8330_CMD_SET_PWMCFG2 0x71 /* Set PWM Timer 2 Conf iguration Control Register. This register defines interrupt masking and the output behavior for the associated PWM channel */ #define LM8330_CMD_SET_TIMSWRES 0x78 /* Set PWM Timer Software Reset Registers. Reset control on all PWM timers */ #define LM8330_CMD_READ_TIMRIS 0x7A /* Read PWM Timer Interrupt Status Register. This register returns the raw interrupt status from the PWM timers 0,1 and 2.*/ #define LM8330_CMD_READ_TIMMIS 0x7B /* Read PWM Timer Masked Interrupt Status Register. This register returns the masked interrupt status from the PWM timers 0, 1 and 2. */ #define LM8330_CMD_SET_TIMIC 0x7C /* Set PWM Timer Interrupt Clear Register. This register clears timer and pattern interrupts. */ #define LM8330_CMD_SET_PWMWP 0x7D /* Set PWM Timer Pattern Pointer Register. Pointer to the pattern position inside the configuration register, which will be overwritten by the next write access to be PWMCFG register */ #define LM8330_CMD_SET_PWMCFG 0x7E /* PWM Script Register. Two-byte pattern storage register for a PWM script command indexed by PWMWP. PWMWP is automatically incremented*/ #define LM8330_CMD_SET_I2CSA 0x80 /* Set Slave Address Register. The address is internally applied after the next I2C STOP*/ #define LM8330_CMD_READ_MFGCODE 0x80 /* Read Manufacturer Code Register*/ #define LM8330_CMD_READ_SWREV 0x81 /* Read Software revision code of the LM8330 */ #define LM8330_CMD_SWRESET 0x81 /* Software Reset Register. The reset is only applied if the supplied parameter has the inverted value as SWBIT*/ #define LM8330_CMD_RSTCTRL 0x82 /* Software reset of specific parts of the LM8330 */ #define LM8330_CMD_RSTINTCLR 0x84 /* Clear NO Init/Power-On Interrupt Register . This register is used to clear the PORIRQ Interrupt. This interrupt is set every time the device returns from RESET (either POR, HW or SW Reset).*/ #define LM8330_CMD_CLKMODE 0x88 /* Clock Mode Register. This register controls the current operating mode of the LM8330 device. */ #define LM8330_CMD_CLKEN 0x8A /* Clock Enable Register. Controls the clock to different functional units. It is used to enable the functional blocks globally and independently */ #define LM8330_CMD_AUTOSLP 0x8B /* Auto-sleep Enable Register. This register controls the Auto-Sleep function of the LM8330 device */ #define LM8330_CMD_AUTOSLPTIL 0x8C /* Auto-Sleep Time Register Low byte. This register defines the activity time. If this time passes without any processing events then the device enters into sleep-mode, but only if AUTOSLP.ENABLE bit is set to 1. */ #define LM8330_CMD_AUTOSLPTIH 0x8D /* Auto-Sleep Time Register High byte*/ #define LM8330_CMD_READ_IRQST 0x91 /* Read Interrupt Global Interrupt Status Register. Returns the interrupt status from various on-chip function blocks */ #define LM8330_CMD_READ_INT 0x91 #define LM8330_CMD_SET_IOCFG 0xA7 /* Input/Output Pin Mapping Configuration Register. Configures usage of KPY[11:8] if not used for Keypad. */ #define LM8330_CMD_SET_IOPC0 0xAA /* Pull Resistor Configuration Register 0. Defines the pull resistor configuration for balls KPX[7:0]. */ #define LM8330_CMD_SET_IOPC1 0xAC /* Pull Resistor Configuration Register 1. Defines the pull resistor configuration for balls KPY[7:0].. */ #define LM8330_CMD_SET_IOPC2 0xAE /* Pull Resistor Configuration Register 2. Defines the pull resistor configuration for balls KPY[11:8].. */ /* Interrupt global status. */ #define INT_GPIOIRQ 0x01 /* GPIO interrupt */ #define INT_TIM0IRQ 0x02 /* Timer0 expiry */ #define INT_TIM1IRQ 0x04 /* Timer0 expiry */ #define INT_TIM2IRQ 0x08 /* Timer0 expiry */ #define INT_KBDIRQ 0x40 /* Keyboard interrupt (further key selection in keyboard module */ #define INT_PORIRQ 0x80 /* Supply failure on VCC. Also power-on is considered as an initial supply failure */ /* Keyboard Row Interrupt status. */ #define KINT_RSINT 0x01 /* Raw scan interrupt.Interrupt generated after keyboard scan, if the keyboard status has changed. */ #define KINT_RKLINT 0x02 /* Raw key lost interrupt indicates a lost key-code. */ #define KINT_REVTINT 0x04 /* Raw keyboard event interrupt.At least one key press or key release is in the keyboard event buffer */ #define KINT_RELINT 0x08 /* Raw event lost interrupt. More than 16 keyboard events have been detected and caused the event buffer to overflow */ /* Clock settings (CMD_CLKMODE). */ #define CLK_MODCTL 0x01 /* 00: SLEEP Mode, 01: Operation Mode .Writing to 00 forces the device to immediately enter sleep mode,*/ /* Clock settings (CMD_CLKEN). */ #define CLK_TIMEN 0x04 /* PWM Timer 0, 1, 2 clock enable */ #define CLK_KBDEN 0x01 /* Keyboard clock enable (enables/disables key scan) */ #define SCRIPT_1 //#define SCRIPT_2 //#define SCRIPT_3 static int lm8330_configure(struct lm8330_chip *lm) { int keysize = (lm->size_x << 4) | lm->size_y; int clock = (CLK_TIMEN | CLK_KBDEN); int debounce = lm->debounce_time >> 2; int active = lm->active_time >> 2; /* * Active time must be greater than the debounce time: if it's * a close-run thing, give ourselves a 12ms buffer. */ if (debounce >= active) active = debounce + 3; lm8330_write(lm, 2, LM8330_CMD_AUTOSLP, 0x00); /* disable autoslip */ lm8330_write(lm, 2, LM8330_CMD_CLKMODE, 0x01); /* set Operation mode */ lm8330_write(lm, 2, LM8330_CMD_CLKEN, clock); /* nable keyboard clock end timers */ lm8330_write(lm, 2, LM8330_CMD_SET_KBDSETTLE, 0x80); /* Set the keyscan settle time to 12 msec. */ lm8330_write(lm, 2, LM8330_CMD_SET_KBDBOUNCE, debounce); /* Set the keyscan debounce time */ lm8330_write(lm, 2, LM8330_CMD_SET_KBDSIZE, keysize); /* Set the keyscan matrix size to 5 rows x 10 columns */ lm8330_write(lm, 3, LM8330_CMD_SET_KBDDEDCFG, 0xFF, 0xFF); /* Confirm default value */ lm8330_write(lm, 2,LM8330_CMD_SET_IOCFG, 0x11); /* KPY10-> pwm, KPY11->IRQ */ lm8330_write(lm, 3,LM8330_CMD_SET_IOPC0, 0xAA, 0xAA); /* pull up resistor for row*/ lm8330_write(lm, 3,LM8330_CMD_SET_IOPC1, 0x55, 0x55); /* pulldown resistor for column 0-7*/ lm8330_write(lm, 3,LM8330_CMD_SET_IOPC2, 0x5A, 0x05); /* pulldown resistor for column 8-9*/ lm8330_write(lm, 2,LM8330_CMD_RSTINTCLR, 0x01); /* Clear Power On interrupt */ lm8330_write(lm, 2,LM8330_CMD_SET_KBDIC, 0x03); /* Clear all pending interrupts */ lm8330_write(lm, 2,LM8330_CMD_SET_KBDMSK, 0x0B); /* Configure interrupt masking */ /* PWM0 programming * */ lm8330_write(lm, 2, LM8330_CMD_SET_TIMCFG0, 0x10); /* Interrupt mask for PWM CYCIRQ0 */ lm8330_write(lm, 2, LM8330_CMD_SET_PWMCFG0, 0x08); /* CDIRQ disabled/masked, Pattern Generator disabled, PWM disabled,PWM off-state is low */ lm8330_write(lm, 2, LM8330_CMD_SET_TIMIC, 0x3F); /* This register clears timer and pattern interrupts */ lm8330_write(lm, 2, LM8330_CMD_SET_PWMWP, 0); /* set PWM SCRIPT pointer buffer */ #ifdef SCRIPT_1 // This script outputs a square wave with a duty cycle at 25%. Why??????????????????????????????? lm8330_write(lm, 3, LM8330_CMD_SET_PWMCFG, 0x40, 0x00); //0x40FF set duty cycle to 00% lm8330_write(lm, 3, LM8330_CMD_SET_PWMCFG, 0x01, 0x7F); //ramp 1 inc 126 lm8330_write(lm, 3, LM8330_CMD_SET_PWMCFG, 0x01, 0x7F); //ramp 1 inc 126 lm8330_write(lm, 3, LM8330_CMD_SET_PWMCFG, 0x01, 0xFF); //ramp 1 dec 126 lm8330_write(lm, 3, LM8330_CMD_SET_PWMCFG, 0x01, 0xFF); //ramp 1 dec 126 lm8330_write(lm, 3, LM8330_CMD_SET_PWMCFG, 0x00, 0x00); //goto start script #endif #ifdef SCRIPT_2 //This script outputs a square wave with a duty cycle that varies continuously from 0% to 25% (a minute or two) then outputs a square wave with a duty cycl 50%. Why?????????????????????????? lm8330_write(lm, 3, LM8330_CMD_SET_PWMCFG, 0x40, 0x7F); //set duty cycle to 50% lm8330_write(lm, 3, LM8330_CMD_SET_PWMCFG, 0xBF, 0xC1); //loop lm8330_write(lm, 3, LM8330_CMD_SET_PWMCFG, 0x40, 0x00); //set duty cycle to 0% lm8330_write(lm, 3, LM8330_CMD_SET_PWMCFG, 0xBF, 0xC1); //loop lm8330_write(lm, 3, LM8330_CMD_SET_PWMCFG, 0x40, 0xFF); //set duty cycle to 100% lm8330_write(lm, 3, LM8330_CMD_SET_PWMCFG, 0xBF, 0xC1); //loop lm8330_write(lm, 3, LM8330_CMD_SET_PWMCFG, 0x00, 0x00); //go to start script #endif #ifdef SCRIPT_3 //This script outputs a square wave with a duty cycle that varies continuously from 0% to 25% (a minute or two), then stop. Why?????????????????????????? lm8330_write(lm, 3, LM8330_CMD_SET_PWMCFG, 0x40, 0x7F); //set duty cycle to 50% lm8330_write(lm, 3, LM8330_CMD_SET_PWMCFG, 0xBF, 0xC1); //loop lm8330_write(lm, 3, LM8330_CMD_SET_PWMCFG, 0x40, 0x00); //set duty cycle to 0% lm8330_write(lm, 3, LM8330_CMD_SET_PWMCFG, 0xBF, 0xC1); //loop lm8330_write(lm, 3, LM8330_CMD_SET_PWMCFG, 0x40, 0xFF); //set duty cycle to 100% lm8330_write(lm, 3, LM8330_CMD_SET_PWMCFG, 0xBF, 0xC1); //loop lm8330_write(lm, 3, LM8330_CMD_SET_PWMCFG, 0x00, 0x00); //go to start #endif /* Command repeated because some keypad configuration instruction puts it in sleep mode. ?????????????? */ lm8330_write(lm, 2, LM8330_CMD_CLKMODE, 0x01); /*set Operation mode */ lm8330_write(lm, 2, LM8330_CMD_SET_PWMCFG0, 0x06); /* Start pwm script /* * Not much we can do about errors at this point, so just hope * for the best. */ return 0; }