|
|
View previous topic :: View next topic |
Author |
Message |
ceronimo
Joined: 19 Jan 2010 Posts: 9
|
18F4550 USB connection and the problem int_rda |
Posted: Sat Jun 09, 2012 2:46 am |
|
|
Hello friends,
I am working on a project. 18F4550 with USB connectivity, 4x20 LCD, a channel ADC, temperature sensor DS18B20 UFM-m11 with the rf module and that I'm using udea company. Rf module, everything works except for the project. Communicates with the pc via usb circuit with C #. RF module receives power circuit module according to the quality pice 3 bytes "$ BC" is sending data. But that pic is two bytes. Aldıklarıda is wrong datas or data that the first two are correct. 3. data that does not never. Codes below. Meanwhile, strong rf module. 16f628a-related circuit with another circuit "$ BC" comes datas. What is the problem. Please help, I'm about to go haywire.
Code: |
#include <18F4550.h>
#device ADC=10 //10 bit adc kullanılacak.
#include <math.h>
#fuses HSPLL,USBDIV,PLL5,NOPUT,CPUDIV4,VREGEN,NOWDT,NOPROTECT,NOLVP,NODEBUG,MCLR
#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,STOP=1) // RS232 protokolünün 9600 bit/sn baud hızında olacağını ve
// TX,RX uçlarının hangi pinler olacağını tanımlıyor
// parity bitinin olmadığını, stop bitinin 1 bit olacağı belirtiliyor
#use fast_io(a) //Bu komut satırı yazılmazsa ADC çalışmıyor.
#define USB_HID_DEVICE FALSE //İnsan arabirim devresi için burası TRUE olacak ve
#define USB_EP1_TX_ENABLE USB_ENABLE_BULK //turn on EP1(EndPoint1) for IN yığın/interrupt transfers
#define USB_EP1_RX_ENABLE USB_ENABLE_BULK //turn on EP1(EndPoint1) for OUT yığın/interrupt transfers
#define USB_EP1_TX_SIZE 10 //Uçnokta1 için maksimum alınacak ve gonderilecek
#define USB_EP1_RX_SIZE 10 //veri boyutu (32 byte)
#include <Master_LCD420.c>
#include <my_DS18B20.c> //my_DS18B20.c dosyası programa dahil edildi.
#include <pic18_usb.h> //Microchip PIC18Fxx5x Hardware layer for CCS's PIC USB driver
#include <MY_USB_Device.h> //USB configuration and descriptors for this project
#include <usb.c> //handles usb setup tokens and get descriptor reports
#define USB_CON_SENSE_PIN PIN_D2 // wired as above
#define UcNokta1 1
#define Komut gelen_paket[0]
#define param1 gelen_paket[1]
//Komutlar
#define LED_Komutu 0x01
#define Role_Komutu 0x02
#define ADC_Komutu 0x03
#define Motor_ISI_Komutu 0x04
#define yesil_LED PIN_D1
#define kirmizi_LED PIN_D0
#define role PIN_E0
#define LED_ON output_high
#define LED_OFF output_low
char veri[30];
float body_temp,gerilim;//,ADC_deger1=0; //float 32 bitlil ondalıklı sayıyı ifade eder.
unsigned int16 ADC_deger1 = 0;
unsigned int8 veri_a,veri_b,isi_a,isi_b; //ADC nin ADRESL ve ADRESH baytları
#byte SPBRGH=0xFB0
#byte SPBRG=0xFAF
#byte BAUDCON= 0xFB8
#byte TXSTA=0xFAC
#byte RCSTA=0xFAB
#bit TXEN= TXSTA.5
#bit SYNC=TXSTA.4
#bit SENDB=TXSTA.3
#bit BRGH=TXSTA.2
#bit SPEN=RCSTA.7
#bit BRG16=BAUDCON.3
//******************************************************************************
#int_rda // RX ucuna veri gelince meydane gelen kesme
void rda_isr()
{
disable_interrupts(int_rda); // int_rda kesmesini pasif yap
output_high(pin_d0); // RC5 çıkışı lojik-1
output_high(pin_d1); // RC5 çıkışı lojik-1
//gets(veri);
veri[0]=getchar();
write_eeprom(0,veri[0]);
veri[1]=getchar();
write_eeprom(1,veri[1]);
veri[2]=getchar();
write_eeprom(2,veri[2]);
if ((veri[0]==36)&&(veri[1]==67)&&(veri[2]==79)) //$CO geldi ise, kanal değişiklik onay bilgisi gelmiştir.
{
output_low(pin_d0); // RC5 çıkışı lojik-1
}
clear_interrupt(int_rda);
//disable_interrupts(int_rda);
enable_interrupts(int_rda); //serial işlemi bitince bu kesme aktif yapılmakta.
}
//*********************************ADC OKUNUYOR*********************************
unsigned int16 ADC_Oku(int8 kanal)
{
unsigned int16 olcum=0;
set_adc_channel(kanal); //RA0/AN0 ucundaki analog sinyal 10 bit A/D işlemine tabii tutulacak.
delay_us(20); //Kanal seçiminden sonra mutlaka 20us beklenmeli.
olcum = read_adc(); //AN0 girişindeki analog sinyal okunup dijitale çevrildi. olcum isimli değişkene atıldı.
return olcum;
}
//***************************LED TERSLE*****************************************
void tersle()
{
output_toggle(pin_D0);
delay_ms(500);
}
//******************************************************************************
void isi_oku()
{
body_temp=ds1820_read(); //Isı sensöründen sıcaklık bilgisi okunup body_temp değişkenine aktarılıyor.
}
//****************************KALAN SÜRE HESAPLANIYOR***************************
void user_init(void)
{
setup_adc_ports(AN0);
setup_adc(ADC_CLOCK_DIV_16);
set_tris_a(0b00000001); //PORTA0 analog giriş, diğerleri çıkış yapıldı.
set_tris_b(0b00010000); //PORTB4 boot butonu nedeniyle giriş
set_tris_c(0b10000000); //PORTC İLK 3 PİN ÇIKIŞ DİĞERLERİ GİRİŞ
set_tris_d(0b00000100); //PORTD ÇIKIŞ
set_tris_e(0x00); //PORTE ÇIKIŞ
output_b(0b00000000); //
output_c(0x00);
output_d(0b00000000); //ISD nin Play ucuna başalngıçta 1 verip çalmasını engelliyoruz.
output_a(0x00);
output_e(0x00);
lcd_init(); // lcd hazırlık
}
//******************************************************************************
void main(void)
{
byte sayac=0;
byte gelen_paket[10]; //gelen paket
byte gond_paket[10]; //gönderilecek paket
//Sistemi başlat
user_init();
// TXEN=1; //Transmit enabled
SYNC=0; //Asynchronous mode
SPBRGH=0;
SPBRG=25; //HSPLL FREKANSI CPUDIV AYARINDAN DOLAYI 6 YA BÖLÜNDÜĞÜNDEN PİCİN ÇALIŞMA FREKANSI 16MHz OLMUŞ OLUYOR.
BRG16=0; //8-bit Baud Rate Generator – SPBRG only (Compatible mode), SPBRGH value ignored
BRGH=0; //Low speed
// SPEN=1; //Serial port enabled (configures RX/DT and TX/CK pins as serial port pins)
usb_init(); //USB Başlatılıyor.
usb_task(); //USB çevre birimleri ve kesmeleri etkin
clear_interrupt(int_rda);
enable_interrupts(int_rda); // int_rda kesmesi aktif, USART arabirim kesmesi aktif.
enable_interrupts(GLOBAL); // Aktif edilen tüm kesmelere izin ver
printf("%c%c%c",0x24,0x43,0x30); //UFM-M11 için 0. kanal seçildi. Kanal 0: 433,05 MHz
//UFM-M11 kanal değişiklik onay bilgisi olarak 0x24,0x43,0x4F yani $CO gönderir.
while(1)
{
//output_low(pin_d1); //USB bağlantısı yokken d0 lojik0 olur.
//tersle();
isi_oku();
ADC_deger1=ADC_Oku(0);
veri_a=make8(ADC_deger1,0);//ADC nin ADRESL baytı elde edildi.
veri_b=make8(ADC_deger1,1);//ADC nin ADRESH baytı elde edildi.
gerilim=ADC_deger1*0.01956; //10 bit çözünürlük ve max.20V DC ölçülüyor. Bu nedenle 0.01956 ile çarpıldı.
lcd_gotoxy(1,4);
printf(lcd_putc,"Vucut Isisi: ");
lcd_gotoxy(1,3);
printf(lcd_putc,"Nabiz: ");
lcd_gotoxy(1,2);
printf(lcd_putc,"Motor Isisi: %4.1f%cC ",body_temp,223);
lcd_gotoxy(1,1);
printf(lcd_putc,"Aku Voltaji: %2.1fV",gerilim);
while((usb_enumerated())&& (input(USB_CON_SENSE_PIN)==1)) //Cihaz PC tarafından tanınmışsa (yapılandırılmışsa)
{
//output_high(pin_d1); //USB bağlantısı kurulduğunda d0 lojik1 olur.
if (usb_kbhit(UcNokta1)) //Eğer pc'den yeni bir paket geldiyse
{
usb_get_packet(UcNokta1, gelen_paket, 10); //paketi oku
switch(Komut)
{
case LED_Komutu: //#define LED_Komutu 0x01
if (param1 == 0) {LED_ON(yesil_LED);};
if (param1 == 1) {LED_OFF(yesil_LED);};
if (param1 == 2) {LED_ON(kirmizi_LED);};
if (param1 == 3) {LED_OFF(kirmizi_LED);};
break;
case Role_Komutu: //#define Role_Komutu 0x02
if(param1==1){output_bit(role,1);};
if(param1==0){output_bit(role,0);};
break;
case ADC_Komutu: //#define ADC_Komutu 0x03
ADC_deger1=ADC_Oku(0);
gond_paket[0] = Komut;
gond_paket[1] = veri_a; //ADC nin ADRESL baytı pc ye gönderilior.
gond_paket[2] = veri_b; //ADC nin ADRESH baytı pc ye gönderilior.
sayac = 0x03;
break;
case Motor_ISI_Komutu: //#define Motor_ISI_Komutu 0x04
isi_a=floor(body_temp);
body_temp=ds1820_read();
gond_paket[0] = Komut;
gond_paket[1] = isi_a;
gond_paket[2] = isi_b;
sayac = 0x03;
break;
default: ; break;
}
}
if(sayac!=0)
{
usb_put_packet(UcNokta1, gond_paket, sayac, USB_DTS_TOGGLE);
sayac = 0;
Komut = 0;
}
}
}
} |
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Sat Jun 09, 2012 4:58 am |
|
|
first....
You must add 'errors' to the uses rs232(...options). This will prevent UART 'stalling' ot 'lockup'.
try with that modification and report back... |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Sat Jun 09, 2012 5:57 am |
|
|
Code: | #byte SPBRGH=0xFB0
#byte SPBRG=0xFAF
#byte BAUDCON= 0xFB8
#byte TXSTA=0xFAC
#byte RCSTA=0xFAB
#bit TXEN= TXSTA.5
#bit SYNC=TXSTA.4
#bit SENDB=TXSTA.3
#bit BRGH=TXSTA.2
#bit SPEN=RCSTA.7
#bit BRG16=BAUDCON.3 | Remove all this and related code. The CCS compiler will configure these registers for you in the #use RS232 line.
If you don't trust the compiler, then have a look at the list file (*.lst) and compare with your settings.
Code: | set_tris_a(0b00000001); //PORTA0 analog giriş, diğerleri çıkış yapıldı.
set_tris_b(0b00010000); //PORTB4 boot butonu nedeniyle giriş
set_tris_c(0b10000000); //PORTC İLK 3 PİN ÇIKIŞ DİĞERLERİ GİRİŞ
set_tris_d(0b00000100); //PORTD ÇIKIŞ
set_tris_e(0x00); //PORTE ÇIKIŞ | Normally you don't have to set the TRIS registers as the CCS compiler will set them for you on every I/O operation. Only in special situations where you need the maximum speed you can choose to set the TRIS registers yourself, but that is in the end of your project when you are optimizing. You then have to overrule the compiler by defining fast_io for these ports. Now you have only defined fast_io for port_A, this is not consistent. Either set fast_io for all ports, or set only the TRIS register for the fast ports.
Code: | void rda_isr()
{
disable_interrupts(int_rda); // int_rda kesmesini pasif yap
...
enable_interrupts(int_rda); //serial işlemi bitince bu kesme aktif yapılmakta. | Not an error but unnecessary code. Once you are in the interrupt handler the PIC hardware will have disabled the global interrupt flag. Hence, no other interrupts can occur and it doesn't make any sense to add extra code for disabling/enabling the interrupt.
Also, the interrupt will be cleared by reading the character from the UART. Calling clear_interrupt(int_rda) from inside the ISR is therefor wrong; if a second character is waiting to be read you will remove it with this call and loose the character.
Just a few more hints for writing more readable programs:
Code: | if ((veri[0]==36)&&(veri[1]==67)&&(veri[2]==79)) //$CO geldi ise, kanal değişiklik onay bilgisi gelmiştir. | can be replaced by Code: | if ((veri[0]=='$')&&(veri[1]=='C')&&(veri[2]=='O')) //$CO geldi ise, kanal değişiklik onay bilgisi gelmiştir.
|
Add #case to your program, it will make the compiler case sensitive. Sometimes annoying but it will ensure you write all variables with the same capitalization and so easier to read. Good practice is to write constants in all capital characters (int_rda and pin_d0 become INT_RDA & PIN_D0) |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Sat Jun 09, 2012 7:35 am |
|
|
The big problem though is int_rda.
You need to remove just about everything you have inside it....
First, there is no point in disabling the interrupt, or clearing the interrupt, or enabling the interrupt inside the handler. The compiler clears the interrupt for you, Unless_ you specify 'no_clear', and all interrupts are automatically disabled when a handler is called.
The big problem though is that you wait for multiple characters. You _must not_ do this. The interrupt means that _one_ character is ready for you to read. Just one. You wait for three characters to arrive, and write these to the EEPROM. EEPROM writes take about 4mSec each. So your code is effectively 'stuck' inside the INT_RDA handler for at least 12mSec (longer if the characters do not arrive immediately). USB, _requires_ that replies are issued to certain commands inside 10mSec. All the time you are stuck inside INT_RDA, USB responses are not happening. Also the time taken to write, is longer than the time between characters, so characters will be missed if they arrive without break.
You need to start again. Base your INT_RDA code on EX_SISR, making a _circular_ buffer, that stores just one character, and gets out ASAP.
Then have you main code implement a little state machine, (a search here, or online, will find examples), which if the three required characters come, drops D0, and stores the characters as required into the EEPROM.
Though there are times when it can be ignored, the old 'mantra' really does apply, especially when running USB - interrupt handlers should do the _minimum_ necessary to handle the event the interrupt signifies, and get out again ASAP.
There is a separate problem that your CPU is _not_ clocking at 20MHz.
You have HSPLL selected, which means that the CPU clock comes from the USB PLL. With a 20MHz crystal (presumably, since you have PLL5, which implies division by 5 before feeding the PLL). The output of the PLL is 96MHz, which is then divided by 2 to feed the USB. CPUDIV4, then gives '11' as the bit pattern to the divider chain, which when operating from the USB clock divides this by 6 (I know silly isn't it...). So your CPU is actually running at 16MHz, not 20MHz, which will prevent RS232 from receiving characters properly....
Best Wishes |
|
|
ceronimo
Joined: 19 Jan 2010 Posts: 9
|
|
Posted: Sat Jun 09, 2012 8:05 am |
|
|
# use rs232 added a routine part of ERRORS.
Fast_io for all ports have added.
DS18B20 has been canceled. Operation of stopped.
Trying to uninstall the DS18B20 fast_io routines for all ports, but this time the ADC is disabled.
also
Code: | #byte SPBRGH=0xFB0
#byte SPBRG=0xFAF
#byte BAUDCON= 0xFB8
#byte TXSTA=0xFAC
#byte RCSTA=0xFAB
#bit TXEN= TXSTA.5
#bit SYNC=TXSTA.4
#bit SENDB=TXSTA.3
#bit BRGH=TXSTA.2
#bit SPEN=RCSTA.7
#bit BRG16=BAUDCON.3 |
and
Code: | SPEN=1;
SYNC=0; //Asynchronous mode
SPBRGH=0;
SPBRG=25; //HSPLL FREKANSI CPUDIV AYARINDAN DOLAYI 6 YA BÖLÜNDÜĞÜNDEN PİCİN ÇALIŞMA FREKANSI 16MHz OLMUŞ OLUYOR.
BRG16=0; //8-bit Baud Rate Generator – SPBRG only (Compatible mode), SPBRGH value ignored
BRGH=0; //Low speed |
rs232 communication routines in the program did not improve and when. Lack of communication continues. |
|
|
ceronimo
Joined: 19 Jan 2010 Posts: 9
|
|
Posted: Sat Jun 09, 2012 8:23 am |
|
|
Hi Ttelmah,
Can you write it for me sample code in accordance with my program you mind? |
|
|
ceronimo
Joined: 19 Jan 2010 Posts: 9
|
|
Posted: Mon Jun 11, 2012 2:36 pm |
|
|
I wrote a simple code in the following link. nidhimittalhada wrote the code works.
http://www.ccsinfo.com/forum/viewtopic.php?t=43483
Code: |
#include <18F4550.h>
#fuses HSPLL, NOWDT, PLL5, CPUDIV1, USBDIV, NOXINST
#use delay (clock=48000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,STOP=1)
void main() {
char c[5];
printf("%c%c%c",0x24,0x43,0x30);
while(TRUE) {
output_toggle(pin_d0);
if (kbhit() ) {
c[0]=getc();
c[1]=getc();
c[2]=getc();
write_eeprom(0,c[0]);
write_eeprom(1,c[1]);
write_eeprom(2,c[2]);
}
}
}
|
Here the following events,
UFM-M11 module is sent to the channel selector code. 0x24, 0x43, 0x30
0. the channel is said to be used. Ok when you receive this code in the module as a pic18f4550 of data 0x24, 0x43, 0x4F, ie "$ CO" needed to send.
3 bytes of data sent to the above program is run (0x24, 0x43, 0x30
) Just taken. It seem to have a reverberation. I use 4093 version of the compiler
Please help.[url][/url] |
|
|
ceronimo
Joined: 19 Jan 2010 Posts: 9
|
|
Posted: Mon Jun 11, 2012 2:58 pm |
|
|
I using micro-easypic5 board.
I noticed that. 18F4550 programmed on the system board. I did read through the plate without removing. has just sent in the eeprom data. Other 18F4550 did the same procedure. The same conclusion. 20 MHz crystal. 22pF capacitor.
Bi very strange situation. |
|
|
|
|
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
|