|
|
View previous topic :: View next topic |
Author |
Message |
kurtzweber
Joined: 18 Oct 2012 Posts: 4
|
USB keyboard with 18f14k50 |
Posted: Mon Oct 22, 2012 6:24 am |
|
|
Hello!
I'm working on a project with a 18f14k50 PIC. I need to implement a keyboard HID device and I'm working with the provided examples.
My first attempt is to simply send "Hello" string every 10sec, here's my code:
Code: | #include "PwdHID.h"
#include "PwdHID_desc.h"
#include <pic18_usb.h>
#include <usb_bootloader.h>
#include <usb.c>
#define KB_MODIFIER_LEFT_SHIFT 2
void main() {
set_tris_c(0x00);
output_low(LED_RED);
output_low(LED_YELLOW);
output_low(LED_GREEN);
usb_init_cs();
while(TRUE) {
usb_task();
if(usb_enumerated()) {
output_high(LED_GREEN);
sendChar('H');
sendChar('e');
sendChar('l');
sendChar('l');
sendChar('o');
sendChar('\n');
delay_ms(10000);
}
}
}
void sendChar(char c) {
unsigned int8 tx_msg[7];
unsigned int8 leds;
unsigned int16 scancode;
if (usb_tbe(1)) {
memset(tx_msg, 0x00, sizeof(tx_msg));
scancode = ToHidKeyboardScancode(c);
if(bit_test(scancode, 8)) tx_msg[0] = KB_MODIFIER_LEFT_SHIFT;
tx_msg[2] = scancode;
usb_put_packet(1, tx_msg, sizeof(tx_msg), USB_DTS_TOGGLE);
}
if(usb_kbhit(1)) usb_get_packet(1, &leds, 1);
}
unsigned int16 ToHidKeyboardScancode(char c)
{
unsigned int16 shift = 0;
if ((c>='A')&&(c<='Z'))
{
c = tolower(c);
shift = 0x100;
}
if ((c>='a')&&(c<='z'))
{
return(((c-='a')+4)|shift);
}
if ((c>='1')&&(c<='9'))
{
return((c-='0')+0x1D);
}
switch(c)
{
case '!': return(0x11E);
case '@': return(0x11F);
case '#': return(0x120);
case '$': return(0x121);
case '%': return(0x122);
case '^': return(0x123);
case '&': return(0x124);
case '*': return(0x125);
case '(': return(0x126);
case ')': return(0x127);
case '0': return(0x27);
case '\n': return(0x28); //enter
case '\r': return(0x28); //enter
case '\b': return(0x2A); //backspace
case '\t': return(0x2B); //tab
case ' ': return(0x2C); //space
case '_': return(0x12D);
case '-': return(0x2D);
case '+': return(0x12E);
case '=': return(0x2E);
case '{': return(0x12F);
case '[': return(0x2F);
case '}': return(0x130);
case ']': return(0x30);
case '|': return(0x131);
case '\\': return(0x31);
case ':': return(0x133);
case ';': return(0x33);
case '"': return(0x134);
case '\'': return(0x34);
case '~': return(0x135);
case '`': return(0x35);
case '<': return(0x136);
case ',': return(0x36);
case '>': return(0x137);
case '.': return(0x37);
case '?': return(0x138);
case '/': return(0x38);
}
} |
When I run it, my PC correctly detect the new device but it starts to send only 'H':
Where am I wrong?
Thanks! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19559
|
|
Posted: Mon Oct 22, 2012 7:08 am |
|
|
Several little things.
First, rethink having a 10 second delay in the main loop. Have a timer interrupt 'ticking' at some convenient interval, and use this to do a countdown. USB, may run into problems if you pause this long between calling the task handler.
Big one though is that the key needs to release. You are sending a packet for the first key being pressed, and it is never released. Hence the computer will see it continuously repeating. To send a character, you need to send a key (with the required modifiers), and then release the key.
Best Wishes |
|
|
kurtzweber
Joined: 18 Oct 2012 Posts: 4
|
|
Posted: Mon Oct 22, 2012 8:32 am |
|
|
Thanks for your reply!
To release the key, I thought to send a message with all 0x00 but nothing changes:
Quote: | // tx_msg[2:6] = an array of held down keys. a=4, b=5, etc.
// if msg[2:7]={0} then no keys are held down |
Code: | void send_char(char c) {
unsigned int8 tx_msg[7];
unsigned int8 leds;
unsigned int16 scancode;
if (usb_tbe(1)) {
memset(tx_msg, 0x00, sizeof(tx_msg));
scancode = ToHidKeyboardScancode(c);
if(bit_test(scancode, 8)) tx_msg[0] = KB_MODIFIER_LEFT_SHIFT;
tx_msg[2] = scancode;
usb_put_packet(1, tx_msg, sizeof(tx_msg), USB_DTS_TOGGLE);
// release key
memset(tx_msg, 0x00, sizeof(tx_msg));
usb_put_packet(1, tx_msg, sizeof(tx_msg), USB_DTS_TOGGLE);
}
} |
|
|
|
kurtzweber
Joined: 18 Oct 2012 Posts: 4
|
|
Posted: Mon Oct 22, 2012 9:36 am |
|
|
Hello!
I added a small delay (100ms) between the two "usb_put_packet" and now it sends the key, but just the first one ('H'), both using printf() or calling the sub manually... very strange!
I changed also the delay function:
Code: | #include "PwdHID.h"
#include "PwdHID_desc.h"
#include <pic18_usb.h>
#include <usb_bootloader.h>
#include <usb.c>
#define KB_MODIFIER_LEFT_SHIFT 2
int1 time_expired = FALSE;
unsigned int8 timer0_count;
#int_timer0
void int_timer0_handler() {
set_timer0(28036);
timer0_count++;
if(timer0_count == 100) {
time_expired = TRUE;
timer0_count = 0;
}
}
void main() {
set_tris_c(0x00);
output_low(LED_RED);
output_low(LED_YELLOW);
output_low(LED_GREEN);
setup_timer_0(T0_INTERNAL | T0_DIV_32);
set_timer0(28036);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
usb_init_cs();
while(TRUE) {
usb_task();
if(usb_enumerated()) {
output_high(LED_GREEN);
if(time_expired) {
//printf(send_char, "Hello World!\n");
send_char('H');
send_char('e');
send_char('l');
send_char('l');
send_char('o');
time_expired = FALSE;
}
}
}
}
void send_char(char c) {
unsigned int8 tx_msg[7];
unsigned int8 leds;
unsigned int16 scancode;
if (usb_tbe(1)) {
memset(tx_msg, 0x00, sizeof(tx_msg));
scancode = ToHidKeyboardScancode(c);
if(bit_test(scancode, 8)) tx_msg[0] = KB_MODIFIER_LEFT_SHIFT;
tx_msg[2] = scancode;
usb_put_packet(1, tx_msg, sizeof(tx_msg), USB_DTS_TOGGLE);
// release key
delay_ms(100);
memset(tx_msg, 0x00, sizeof(tx_msg));
usb_put_packet(1, tx_msg, sizeof(tx_msg), USB_DTS_TOGGLE);
}
}
unsigned int16 ToHidKeyboardScancode(char c)
{
unsigned int16 shift = 0;
if ((c>='A')&&(c<='Z'))
{
c = tolower(c);
shift = 0x100;
}
if ((c>='a')&&(c<='z'))
{
return(((c-='a')+4)|shift);
}
if ((c>='1')&&(c<='9'))
{
return((c-='0')+0x1D);
}
switch(c)
{
case '!': return(0x11E);
case '@': return(0x11F);
case '#': return(0x120);
case '$': return(0x121);
case '%': return(0x122);
case '^': return(0x123);
case '&': return(0x124);
case '*': return(0x125);
case '(': return(0x126);
case ')': return(0x127);
case '0': return(0x27);
case '\n': return(0x28); //enter
case '\r': return(0x28); //enter
case '\b': return(0x2A); //backspace
case '\t': return(0x2B); //tab
case ' ': return(0x2C); //space
case '_': return(0x12D);
case '-': return(0x2D);
case '+': return(0x12E);
case '=': return(0x2E);
case '{': return(0x12F);
case '[': return(0x2F);
case '}': return(0x130);
case ']': return(0x30);
case '|': return(0x131);
case '\\': return(0x31);
case ':': return(0x133);
case ';': return(0x33);
case '"': return(0x134);
case '\'': return(0x34);
case '~': return(0x135);
case '`': return(0x35);
case '<': return(0x136);
case ',': return(0x36);
case '>': return(0x137);
case '.': return(0x37);
case '?': return(0x138);
case '/': return(0x38);
}
}
|
thanks again! |
|
|
kurtzweber
Joined: 18 Oct 2012 Posts: 4
|
|
Posted: Mon Oct 22, 2012 11:32 am |
|
|
Ok solved
you need a delay after each send... now I'm using 100ms but from the examples provided it seems you can use 10ms:
Code: | // release key
delay_ms(100);
memset(tx_msg, 0x00, sizeof(tx_msg));
usb_put_packet(1, tx_msg, sizeof(tx_msg), USB_DTS_TOGGLE);
delay_ms(100); |
|
|
|
egemenakbas
Joined: 10 Mar 2021 Posts: 2
|
|
Posted: Wed Mar 10, 2021 9:56 am |
|
|
kurtzweber wrote: | Ok solved
you need a delay after each send... now I'm using 100ms but from the examples provided it seems you can use 10ms:
Code: | // release key
delay_ms(100);
memset(tx_msg, 0x00, sizeof(tx_msg));
usb_put_packet(1, tx_msg, sizeof(tx_msg), USB_DTS_TOGGLE);
delay_ms(100); |
|
Hi, can you share ccs c project files to me?
thanks |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Mar 11, 2021 12:50 am |
|
|
kurtzweber's last post was on Oct 22, 2012. That was many years ago.
Don't expect a reply. |
|
|
egemenakbas
Joined: 10 Mar 2021 Posts: 2
|
|
Posted: Thu Mar 11, 2021 2:27 am |
|
|
PCM programmer wrote: | kurtzweber's last post was on Oct 22, 2012. That was many years ago.
Don't expect a reply. |
Hi, I noticed but wanted to take a chance I need such a project. Thanks for the return. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9251 Location: Greensville,Ontario
|
|
Posted: Thu Mar 11, 2021 6:18 am |
|
|
You could take any PIC,add a TTL-USB module to do the same 'task'. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19559
|
|
Posted: Thu Mar 11, 2021 7:38 am |
|
|
No, Jay. Most of these modules would be CDC devices, not HID devices.
He wants data as if it comes from a keyboard.
The original posted code sounds as if it was working with the changes
implemented, so it should only be a couple of seconds work to test it.
The reason he was having to add a delay, is a common 'misunderstanding' of
how key scan codes work. To actually simulate a key being typed, you have
to send the 'key scan code', and then a 'key released' code. By sending just
the scan code, the system instead waits for the key repeat interval, and
then 'sees' the key. Hence the delay being needed. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|