Một khách hàng đã nhờ tôi làm thiết bị này ... Một bàn phím tự động " Bấm phím" tương tự như ta gõ trên bàn phím PC, laptop v.v. vậy.
Bàn phím tự động thường được sử dụng cho mục đích : Điều khiển tương tác với máy tính , chơi game ( bấm phím tuần tự)... ( Như là luyện Lever trong Cửu Long Tranh bá ... chẳng hạn )
Không sợ bị các phần mềm Game chặn như là đối với bàn phím được lập trình bằng phần mềm ( còn gọi là phần mềm thứ 3 hỗ trợ game) ,
tốc độ bàn phím cứng này nhanh, chính xác ... phần cứng nhỏ gọn .
--- Sau khi hoàn thành hoàn toàn sản phẩm ( cả phần cứng và phần mềm ) ... do 1 tai nạn giao thông khá nghiêm trọng ... ( suýt thì tôi đã ra đi cùng mỏ hàn,nhựa thông ... to vít --- Rất may mắn là hiện giờ cái đầu và đôi tay vẫn còn hoạt động được) !
hiện tại sản phẩm chưa thể đến tay khách hàng do sự cố trên... Khi tôi nằm đây để điều trị " thương tích " của vụ tai nạn ... mới thấy rằng ...
Mình có rất nhiều đề tài có cái dễ, có cái khó tại sao cứ để 1 chỗ rồi có khi 1 lúc nào đó mang xuống mồ luôn
... Cho không thì không thể ( vì đó là mồ hôi nước mắt, công sức, tiền bạc vào đó nữa .v.v ) .
1 ý nghĩ là tại sao mình không làm theo những cty nước ngoài ? Với ý nghĩ đó ... tôi viết bài này ( Định bụng viết vào luồng tâm tình kỹ thuật ... nhưng thấy không hợp lắm .. đành cho ra đây ).
--- Mỗi đề tài hiện tại, về sau này ( nếu là sản phẩm thương mại mình sản xuất)... tôi sẽ cố gắng có 2 phiên bản :
1) Phiên bản miễn phí : Có 1 số tính năng cơ bản , đủ dùng cơ bản ... mục đích dành cho các đối tượng học sinh, sinh viên... cá nhân nghiên cứu ... tự làm hoặc dựa vào đó để tự phát triển ( nếu thích ) ... và sử dụng cho mục đích cá nhân .
Không dùng cho các đối tượng lấy về nhân bản ... bán hàng chợ ( như 1 số người chỉ biết ngồi , hớt của người khác về rồi đem bán ).
2) Phiên bản thương mại : ĐƯơng nhiên tôi sẽ quản lý , ở bản thương mại sẽ đầy đủ chức năng hơn , chuyên nghiệp hơn ... và có đầy đủ sự hỗ trợ hơn.
-QUAY TRỞ LẠI VẤN ĐỀ :
Tôi chọn PIC18F4550 ( vì tôi sẵn có nó ở trong thùng linh kiện ) ... 1 số chip khác cũng hỗ trợ USB tốt (ARM , PSOC , ST7 ... ) tuy nhiên ở mức độ phổ thông nên dùng PIC cho các bạn dễ kiếm !
Bạn nào yêu thích có thể làm thử :
Đây là sơ đồ của nó :

--- Mã nguồn :
Mã nguồn được viết trên MikroC PRO ( Đơn giản vì MikroC phần mềm khá chuyên nghiệp, dễ sử dụng , thân thiện ... nhiều thư viện ... Nói chung là 1 trong TOP các trình dịch đầu bảng cho những dòng MCU nhỏ nhỏ kiểu này ! )
[MAIN CODE]
--- file khai báo USB để Win nhận đây là 1 KEYBOARD
--- Và đây ... là tất cả Project , test thử trên Proteus
Free_version.zip
-Phiên bản Thương mại ( Tức sản phẩm thương mại) :
thì có thêm 1 số phần mềm hỗ trợ ( đại loại là thế này ) :

( Hiện tại mình đã viết phần mềm cho PC ( WINDOWS ) đã và đang viết cho LINUX , MAC , iOS ... và cả WinCE nữa nếu thấy cần thiết )
--- Chúc các bạn Chủ Nhật vui vẻ
Bàn phím tự động thường được sử dụng cho mục đích : Điều khiển tương tác với máy tính , chơi game ( bấm phím tuần tự)... ( Như là luyện Lever trong Cửu Long Tranh bá ... chẳng hạn )
Không sợ bị các phần mềm Game chặn như là đối với bàn phím được lập trình bằng phần mềm ( còn gọi là phần mềm thứ 3 hỗ trợ game) ,
tốc độ bàn phím cứng này nhanh, chính xác ... phần cứng nhỏ gọn .
--- Sau khi hoàn thành hoàn toàn sản phẩm ( cả phần cứng và phần mềm ) ... do 1 tai nạn giao thông khá nghiêm trọng ... ( suýt thì tôi đã ra đi cùng mỏ hàn,nhựa thông ... to vít --- Rất may mắn là hiện giờ cái đầu và đôi tay vẫn còn hoạt động được) !
hiện tại sản phẩm chưa thể đến tay khách hàng do sự cố trên... Khi tôi nằm đây để điều trị " thương tích " của vụ tai nạn ... mới thấy rằng ...
Mình có rất nhiều đề tài có cái dễ, có cái khó tại sao cứ để 1 chỗ rồi có khi 1 lúc nào đó mang xuống mồ luôn
... Cho không thì không thể ( vì đó là mồ hôi nước mắt, công sức, tiền bạc vào đó nữa .v.v ) .1 ý nghĩ là tại sao mình không làm theo những cty nước ngoài ? Với ý nghĩ đó ... tôi viết bài này ( Định bụng viết vào luồng tâm tình kỹ thuật ... nhưng thấy không hợp lắm .. đành cho ra đây ).
--- Mỗi đề tài hiện tại, về sau này ( nếu là sản phẩm thương mại mình sản xuất)... tôi sẽ cố gắng có 2 phiên bản :
1) Phiên bản miễn phí : Có 1 số tính năng cơ bản , đủ dùng cơ bản ... mục đích dành cho các đối tượng học sinh, sinh viên... cá nhân nghiên cứu ... tự làm hoặc dựa vào đó để tự phát triển ( nếu thích ) ... và sử dụng cho mục đích cá nhân .
Không dùng cho các đối tượng lấy về nhân bản ... bán hàng chợ ( như 1 số người chỉ biết ngồi , hớt của người khác về rồi đem bán ).
2) Phiên bản thương mại : ĐƯơng nhiên tôi sẽ quản lý , ở bản thương mại sẽ đầy đủ chức năng hơn , chuyên nghiệp hơn ... và có đầy đủ sự hỗ trợ hơn.
-QUAY TRỞ LẠI VẤN ĐỀ :
Tôi chọn PIC18F4550 ( vì tôi sẵn có nó ở trong thùng linh kiện ) ... 1 số chip khác cũng hỗ trợ USB tốt (ARM , PSOC , ST7 ... ) tuy nhiên ở mức độ phổ thông nên dùng PIC cho các bạn dễ kiếm !
Bạn nào yêu thích có thể làm thử :
Đây là sơ đồ của nó :
--- Mã nguồn :
Mã nguồn được viết trên MikroC PRO ( Đơn giản vì MikroC phần mềm khá chuyên nghiệp, dễ sử dụng , thân thiện ... nhiều thư viện ... Nói chung là 1 trong TOP các trình dịch đầu bảng cho những dòng MCU nhỏ nhỏ kiểu này ! )
[MAIN CODE]
Code:
// Modifier bytes
#define None 0b00000000
#define LeftCtrl 0b00000001
#define LeftShift 0b00000010
#define LeftAlt 0b00000100
#define LeftGUI 0b00001000
#define RightCtrl 0b00010000
#define RightShift 0b00100000
#define RightAlt 0b01000000
#define RightGUI 0b10000000
/////////////////////////////////
// Key code byte
#define a 4
#define b 5
#define c 6
#define d 7
#define e 8
#define f 9
#define g 10
#define h 11
#define i 12
#define j 13
#define k 14
#define l 15
#define m 16
#define n 17
#define o 18
#define p 19
#define q 20
#define r 21
#define s 22
#define t 23
#define u 24
#define v 25
#define w 26
#define x 27
#define y 28
#define z 29
#define one 30
#define two 31
#define three 32
#define four 33
#define five 34
#define six 35
#define seven 36
#define eight 37
#define nine 38
#define zero 39
#define enter 40
#define escape 41
#define backspace 42
#define tab 43
#define spacebar 44
#define underscore 45
#define equals 46
#define leftbrace 47
#define rightbrace 48
#define backslash 49
#define hash 50
#define semicolon 51
#define comma 54
#define period 55
#define slash 56
#define capslock 57
#define f1 58
#define f2 59
#define f3 60
#define f4 61
#define f5 62
#define f6 63
#define f7 64
#define f8 65
#define f9 66
#define f10 67
#define f11 68
#define f12 69
#define home 74
#define pageup 75
#define delete 76
#define pagedown 78
#define rightarrow 79
#define leftarrow 80
#define downarrow 81
#define uparrow 82
////////////////////
#define start_butt PORTD.F3
bit start;
unsigned char key0time, key1time,key2time,key3time,key4time,key5time,key6time,key7time,key8time, key9time, keyPtime, P_loop;
unsigned char count_skill;
unsigned char stt_cnt, value;
unsigned long time_buff;
unsigned char usbreadbuff[8] absolute 0x500; // Buffers should be in USB RAM
unsigned char usbwritebuff[8] absolute 0x540;
unsigned char usbwriteblank[8] absolute 0x580;
void butt_check();
void key_delay(unsigned long value);
void stroke0();
void stroke1();
void stroke2();
void stroke3();
void stroke4();
void stroke5();
void stroke6();
void stroke7();
void stroke8();
void stroke9();
void strokeP();
/* SUBROUTINE HEADER */
char hid_keyboard_send(char special,char key1,char key2,char key3,char key4,char key5, char key6);
char hid_keyboard_send_EXECUTE();
char hid_keyboard_send_DESKTOP();
char hid_keyboard_send_BLANK();
/* END SUBROUTINE HEADER */
void interrupt(){
USB_Interrupt_Proc(); // USB servicing is done inside the interrupt
}
void main(void){
start=0;
count_skill=0;
ADCON1 |= 0x0A; // analog AN0 --> AN4 ( RA0, RA1, RA2, RA3 , RA5 )
CMCON |= 7; // Disable comparators
PORTA =0x00;
TRISA=0b11101111; // RA4 output
TRISB=0x03;
PORTB=0x00;
PORTC=0x00;
TRISC=0b10111001; // RC7 in for UART RX , RC6 out for UART TX , RC0 in for Freq Cnt , RC1,RC2 out for attenuator
PORTD=0x00;
TRISD=0b00001111;
PORTE=0x00;
TRISE=0b000;
HID_Enable(&usbreadbuff,&usbwritebuff); // Enable HID communication
Delay_ms(2000); // delay 2 sec for usb already
////// Setup for Key Timer !!!
key0time=1;
key1time=1;
key2time=1;
key3time=1;
key4time=1;
key5time=1;
key6time=1;
key7time=1;
key8time=1;
key9time=1;
keyPtime=1; // 1sec
P_loop=3;
///////////////
while(1)
{
butt_check(); // check start/pause every
if(start) // start =1
{
do
{
stroke1();
stroke2();
stroke3();
stroke4();
stroke5();
stroke6();
stroke7();
stroke8();
stroke9();
stroke0();
//// check Skill loop for key P end !!!
count_skill++;
if(count_skill >= P_loop) // match value
{
count_skill=0; // reset count
strokeP();
}
}
while(start);
}
}
}
////////////////// FUNCTIONS ///////////////////////
void butt_check()
{
if(start_butt)
{
start =!start;
if(start==0) {count_skill=0;}
while(start_butt);
Delay_ms(50);
}
}
/////////////////
void key_delay(unsigned long value)
{
while(value--)
{
Delay_ms(1);
butt_check();
if(start==0){value=0;} // exit while
}
}
/* SUBROUTINE */
char hid_keyboard_send(char special,char key1,char key2,char key3,char key4,char key5, char key6)
{
usbwritebuff[0]=special;
usbwritebuff[1]=0x00;
usbwritebuff[2]=key1;
usbwritebuff[3]=key2;
usbwritebuff[4]=key3;
usbwritebuff[5]=key4;
usbwritebuff[6]=key5;
usbwritebuff[7]=key6;
return HID_Write(&usbwritebuff,8);
}
char hid_keyboard_send_EXECUTE() // left windows key + r
{
return hid_keyboard_send(0b00001000,0x15,0x00,0x00,0x00,0x00,0x00);
}
char hid_keyboard_send_DESKTOP() // left windows key + d
{
return hid_keyboard_send(0b00001000,0x07,0x00,0x00,0x00,0x00,0x00);
}
char hid_keyboard_send_BLANK()
{
usbwriteblank[0] = 0x00;
usbwriteblank[1] = 0x00;
usbwriteblank[2] = 0x00;
usbwriteblank[3] = 0x00;
usbwriteblank[4] = 0x00;
usbwriteblank[5] = 0x00;
usbwriteblank[6] = 0x00;
usbwriteblank[7] = 0x00;
return HID_Write(&usbwriteblank,8);
}
///////////////////////////////////////////////////////////
void stroke0()
{
hid_keyboard_send(0x00,zero,0x00,0x00,0x00,0x00,0x00);
hid_keyboard_send_BLANK();
// delay here ( check butt allways in Delay )
time_buff = key0time*1000;
key_delay(time_buff);
}
///////
void stroke1()
{
hid_keyboard_send(0x00,one,0x00,0x00,0x00,0x00,0x00);
hid_keyboard_send_BLANK();
// delay here ( check butt allways in Delay )
time_buff = key1time*1000;
key_delay(time_buff);
}
///////
void stroke2()
{
hid_keyboard_send(0x00,two,0x00,0x00,0x00,0x00,0x00);
hid_keyboard_send_BLANK();
// delay here ( check butt allways in Delay )
time_buff = key2time*1000;
key_delay(time_buff);
}
///////
void stroke3()
{
hid_keyboard_send(0x00,three,0x00,0x00,0x00,0x00,0x00);
hid_keyboard_send_BLANK();
// delay here ( check butt allways in Delay )
time_buff = key3time*1000;
key_delay(time_buff);
}
///////
void stroke4()
{
hid_keyboard_send(0x00,four,0x00,0x00,0x00,0x00,0x00);
hid_keyboard_send_BLANK();
// delay here ( check butt allways in Delay )
time_buff = key4time*1000;
key_delay(time_buff);
}
///////
void stroke5()
{
hid_keyboard_send(0x00,five,0x00,0x00,0x00,0x00,0x00);
hid_keyboard_send_BLANK();
// delay here ( check butt allways in Delay )
time_buff = key5time*1000;
key_delay(time_buff);
}
///////
void stroke6()
{
hid_keyboard_send(0x00,six,0x00,0x00,0x00,0x00,0x00);
hid_keyboard_send_BLANK();
// delay here ( check butt allways in Delay )
time_buff = key6time*1000;
key_delay(time_buff);
}
///////
void stroke7()
{
hid_keyboard_send(0x00,seven,0x00,0x00,0x00,0x00,0x00);
hid_keyboard_send_BLANK();
// delay here ( check butt allways in Delay )
time_buff = key7time*1000;
key_delay(time_buff);
}
///////
void stroke8()
{
hid_keyboard_send(0x00,eight,0x00,0x00,0x00,0x00,0x00);
hid_keyboard_send_BLANK();
// delay here ( check butt allways in Delay )
time_buff = key8time*1000;
key_delay(time_buff);
}
///////
void stroke9()
{
hid_keyboard_send(0x00,nine,0x00,0x00,0x00,0x00,0x00);
hid_keyboard_send_BLANK();
// delay here ( check butt allways in Delay )
time_buff = key9time*1000;
key_delay(time_buff);
}
///////
void strokeP()
{
hid_keyboard_send(LeftShift,p,0x00,0x00,0x00,0x00,0x00);
hid_keyboard_send_BLANK();
// delay here ( check butt allways in Delay )
time_buff = keyPtime*1000;
key_delay(time_buff);
}
///////
/* END SUBROUTINE */
Code:
const unsigned int USB_VENDOR_ID = 0x1304;
const unsigned int USB_PRODUCT_ID = 0x1977;
const char USB_SELF_POWER = 0x80; // Self powered 0xC0, 0x80 bus powered
const char USB_MAX_POWER = 50; // Bus power required in units of 2 mA
const char USB_TRANSFER_TYPE = 0x03; //0x03 Interrupt
const char EP_IN_INTERVAL = 1;
const char EP_OUT_INTERVAL = 1;
const char USB_INTERRUPT = 1;
const char USB_HID_EP = 1;
const char USB_HID_RPT_SIZE = 45; // Keyboard <--> host
/* Device Descriptor */
const struct
{
char bLength; // bLength - Descriptor size in bytes (12h)
char bDescriptorType; // bDescriptorType - The constant DEVICE (01h)
unsigned int bcdUSB; // bcdUSB - USB specification release number (BCD)
char bDeviceClass; // bDeviceClass - Class Code
char bDeviceSubClass; // bDeviceSubClass - Subclass code
char bDeviceProtocol; // bDeviceProtocol - Protocol code
char bMaxPacketSize0; // bMaxPacketSize0 - Maximum packet size for endpoint 0
unsigned int idVendor; // idVendor - Vendor ID
unsigned int idProduct; // idProduct - Product ID
unsigned int bcdDevice; // bcdDevice - Device release number (BCD)
char iManufacturer; // iManufacturer - Index of string descriptor for the manufacturer
char iProduct; // iProduct - Index of string descriptor for the product.
char iSerialNumber; // iSerialNumber - Index of string descriptor for the serial number.
char bNumConfigurations; // bNumConfigurations - Number of possible configurations
} device_dsc =
{
0x12, // bLength
0x01, // bDescriptorType
0x0200, // bcdUSB (USB 2.0)
0x00, // bDeviceClass
0x00, // bDeviceSubClass
0x00, // bDeviceProtocol
8, // bMaxPacketSize0
USB_VENDOR_ID , // idVendor
USB_PRODUCT_ID, // idProduct
0x0002, // bcdDevice
1, // iManufacturer
2, // iProduct
0, // iSerialNumber
0x01 // bNumConfigurations
};
/* Configuration 1 Descriptor */
const char configDescriptor1[] =
{
// Configuration Descriptor
0x09, // bLength - Descriptor size in bytes
0x02, // bDescriptorType - The constant CONFIGURATION (02h)
0x29,0x00, // wTotalLength - The number of bytes in the configuration descriptor and all of its subordinate descriptors
1, // bNumInterfaces - Number of interfaces in the configuration
1, // bConfigurationValue - Identifier for Set Configuration and Get Configuration requests
0, // iConfiguration - Index of string descriptor for the configuration
USB_SELF_POWER, // bmAttributes - Self/bus power and remote wakeup settings
USB_MAX_POWER, // bMaxPower - Bus power required in units of 2 mA
/* Interface Descriptor1 */
0x09, // Size of this descriptor in bytes
0x04, // INTERFACE descriptor type
0, // Interface Number
0, // Alternate Setting Number
2, // Number of endpoints in this intf
0x03, // HID Class code
0, // Subclass code
0, // Protocol code
0, // Interface string index
/* HID Class-Specific Descriptor */
0x09, // Size of this descriptor in bytes
0x21, // HID descriptor type
0x01,0x01, // HID Spec Release Number in BCD format (1.11)
0x00, // Country Code (0x00 for Not supported)
1, // Number of class descriptors, see usbcfg.h
0x22, // Report descriptor type
USB_HID_RPT_SIZE,0x00, //YTS //sizeof(hid_rpt01), // Size of the report descriptor
// Endpoint Descriptor - Inbound to host
0x07, // bLength - Descriptor size in bytes (07h)
0x05, // bDescriptorType - The constant Endpoint (05h)
USB_HID_EP | 0x80, // bEndpointAddress - Endpoint number (0x01) and direction (0x80 = IN to host)
USB_TRANSFER_TYPE, // bmAttributes - Transfer type and supplementary information
0x40,0x00, // wMaxPacketSize - Maximum packet size supported
// This determines the size of the transmission time slot allocated to this device
EP_IN_INTERVAL, // bInterval - Service interval or NAK rate
// Endpoint Descriptor - Outbound from host (i.e. LED indicator status bits)
0x07, // bLength - Descriptor size in bytes (07h)
0x05, // bDescriptorType - The constant Endpoint (05h)
USB_HID_EP, // bEndpointAddress - Endpoint number (0x01) and direction (0x00 = OUT from host)
USB_TRANSFER_TYPE, // bmAttributes - Transfer type and supplementary information
0x40,0x00, // wMaxPacketSize - Maximum packet size supported
// This determines the size of the transmission time slot allocated to this device
EP_OUT_INTERVAL // bInterval - Service interval or NAK rate
};
const struct
{
char report[USB_HID_RPT_SIZE];
} hid_rpt_desc =
{
0x05, 0x01, // G USAGE_PAGE (Generic Desktop)
0x09, 0x06, // L USAGE (Keyboard)
0xa1, 0x01, // M COLLECTION (Application)
0x05, 0x07, // G USAGE_PAGE (Keyboard)
0x19, 0xe0, // L USAGE_MINIMUM (Keyboard LeftControl)
0x29, 0xe7, // L USAGE_MAXIMUM (Keyboard Right GUI)
0x15, 0x00, // G LOGICAL_MINIMUM (0)
0x25, 0x01, // G LOGICAL_MAXIMUM (1)
0x75, 0x01, // G REPORT_SIZE (1)
0x95, 0x08, // G REPORT_COUNT (8)
0x81, 0x02, // M INPUT (Data,Var,Abs)
0x95, 0x01, // G REPORT_COUNT (1)
0x75, 0x08, // G REPORT_SIZE (8)
0x81, 0x01, // M INPUT (Cnst,Var,Abs)
0x95, 0x06, // G REPORT_COUNT (5)
0x75, 0x08, // G REPORT_SIZE (8)
0x15, 0x00, // Logical minimum (0)
0x25, 0x65, // Logical maximum (101)
0x05, 0x07, // G USAGE_PAGE key code
0x19, 0x00, // L USAGE_MINIMUM (0)
0x29, 0x65, // L USAGE_MAXIMUM (101)
0x81, 0x00, // M INPUT (Data,Ary,Abs)
0xc0 // M END_COLLECTION
};
//Language code string descriptor
const struct {
char bLength;
char bDscType;
unsigned int string[1];
} strd1 = {
4,
0x03,
{0x0409}
};
//Manufacturer string descriptor
const struct{
char bLength;
char bDscType;
unsigned int string[20];
}strd2={
34, //sizeof this descriptor string
0x03,
{'Q','u','e','D','u','o','n','g',' ','E','l','e','c','t','r','o','n','i','c','s'}
};
//Product string descriptor
const struct{
char bLength;
char bDscType;
unsigned int string[13];
}strd3={
32, //sizeof this descriptor string
0x03,
{'K','e','y','b','o','a','r','d',' ','F','r','e','e'}
};
//Array of configuration descriptors
const char* USB_config_dsc_ptr[1];
//Array of string descriptors
const char* USB_string_dsc_ptr[3];
void USB_Init_Desc(){
USB_config_dsc_ptr[0] = &configDescriptor1;
USB_string_dsc_ptr[0] = (const char*)&strd1;
USB_string_dsc_ptr[1] = (const char*)&strd2;
USB_string_dsc_ptr[2] = (const char*)&strd3;
}
Free_version.zip
-Phiên bản Thương mại ( Tức sản phẩm thương mại) :
thì có thêm 1 số phần mềm hỗ trợ ( đại loại là thế này ) :
( Hiện tại mình đã viết phần mềm cho PC ( WINDOWS ) đã và đang viết cho LINUX , MAC , iOS ... và cả WinCE nữa nếu thấy cần thiết )
--- Chúc các bạn Chủ Nhật vui vẻ
... sorry nhé !
... khi tung chưởng ... thay vì phải bấm " liên hoàn nút " thì chỉ cần 1 nút ... là ra chưởng ngay ...


) .
Comment