I want to learn and implement CAN BUS protocol. I have implemented UART,SPI,I2C and One Wire Bus protocol using MSP430 Launchpad in software. Now I want to learn about CAN Bus protocol. I have mBed LPC 1768 Cortex M3 Development board. mBed has Can Bus Library but I want to write my own library so that I can learn it in detail, i.e. the way I did for other communication protocols.
I am not able to find suitable resources to start with and the material appears to be scattered on net. Can any one guide how do i write and implement CAN Bus protocol with the development boards available with me.
Thanks
Developing CAN library is relatively easy as compared to I2C or SPI. This is because CAN Controller of your Cortex will take care of most of complex things.
To transmit the data, You have to write ID and Data in designated registers and set bit to transmit data.
This Application note from NXP can be very useful for you.
I would recommend you to implement following functions:
InitCAN - This should set specified Baud Rate of CAN.
SetFilters - Most CAN Controllers come with Acceptance Filters, So it's good to have that
SendData - Make sure you accept Parameters like ID_Type and RTRs etc.
RecieveData - This can be blocking or Interrupt based.
Before beginning, do read CAN Basics to understand. Application notes AN713 and AN754 from Microchip is a good source. Also Vector's site and Wikipedia Article.
Plus, You can always post your doubts here or on Electronics.StackExchange.com :)
Okay so this post is quite old but people may look at it again so:
First of all Can bus is not user friendly protocol like USART or IC2 at all so you have to be very precise about your can bit timing there are tools for that but I suggest you to calculate them by hand. For a microcontroller I would suggest STM32 and be away from PIC series in my opinion. If it's only CAN-BUS without higher level protocols such as SAE J1939, steps are pretty simple and straight forward:
1)Initialize Can
2)Put CAN to configuration mode and remember that you can set baudrate, mask and filters only in configuration mode!
3) Set the baud rate registers.
4) Set the mask and filters. If you need to receive all messages just simply set mask to 0x00. Then filter will be do not care.
5) Set the CAN to the normal or loopback mode. (loopback mode is used for debugging purposes mostly.)
Some remarkable points people try to implement can at the beginning may miss:
*** You need at least 2 working CAN nodes for successfull transmission. (of course with matching baud rate). So if you want to send some data via CAN with 1 node it will not be succesfull. Because your transmitter node will not receive ACK.
*** Most likely you will need a CAN tranciever. Do not forget to put a 100 ohm or similar value resistor between Tx and Rx pins of your tranciever.
I used the software canking to talk to a mcp25050 when I learned how to implement can protocol using an hcs12 dragonboard. It helped a lot because canking will initialize everything for you when u go on the bus and all you have to do is learn how to write and recieve. If you want to learn how to initialize the steps are:
Enables can bus by setting bit on CAN Control Register 1
Enable can initialization Control Register 0
wait until can bus is in initialization mode by checking control register 1 bit
Enables can bus by setting bit on CAN Control Register 1 again and set clock source - Ethier bus clock or eclock
set prescaler baudrate and Tq with Bus timing register
set sample time and prop_seg1, prop_seg2, and phase_seg
set acceptance id on Identifier acceptance register 0-3 or 0-7 - to set your can to recieve everything set those to 00 because when doing a compare the can bus does a ones complement compare with the id coming in
set Identifier mask register 0-3 or 0-7, if you want to not care about any of the bits set them all to FF
set identifier acceptance control register to 32 bit extended or 11 bit - i use 32
set Control Register 0 back to normal mode
wait until bus is normal mode by checking Control Register 1
after this you can start changing registers or reading data to do this you must select the empty can buffer, write your id to write or request data, and then input the address, mask, and value in the 3 transmitter registers if writing and then specify the dlc (3 if writing and 8-1 if reading). to transmit the id and data you then have to set the can transmit flag to equal the can Transmit buffer selection.
** depending on what id you use bit shifting can be tedious so if you are having a problem I would suggest debugging and looking at what your Transmit buffer selection registers are holding. I had this error because i did not shift correctly when i was sending messages to the mcp25050
If your MCU supports CAN Bus, you should start from the related datasheet.
Related
I just started with microchip world.
I'm about to buy a PicKit3 and i've seen it can outputs from 1.8V to 14V MCLR.
The pic i will use is the PIC16F1829 and it should work with MCLR # 5V.
In the datasheet it seems i would need a zener/shunt to limit the voltage.
First of all isn't there a board ready to play with?
Can i use LVP? If so using MPLab 8 IDE how do i change in LVP?
Is the pin connection the same?
Since i haven't bought it yet i would rather avoid burning a pic
Regards,
Notes at the bottom of page 345 in the PIC16F1829 data sheet (DS40001440E) recommends using a voltage limit circuit when using the ICD2 device programmer.
According to Microchip this is "not required" when using the PICkit3.
Get a few extra PIC16F1829 just in case.
You ask about boards ready to use, take a look at the Curisotiy Nano boards
https://www.microforum.cc/topic/9-microchip-xpress-evaluation-boards
These are ready to use and do not need any programmer. You can simply send a file to these devices over USB. They are also have debugging capability.
In terms of the 14V on MCLR, the device is designed to handle whatever pulse will be generated by the PICkit3, so you do not need any protection for the PIC against that. In fact limiting the voltage on that pin will prevent the device from programming so you definitely do not want to do that. If you are however using this pin to connect to other parts on your board the other parts probably will need protection.
You can most definitely use LVP, just be careful, it is possible to use LVP to disable LVP, and then the only way to get it back on is to use HVP!
Lastly in the IDE under programming options you can change the mode there (Use low voltage programming mode entry)
In the IDE i've set the voltage appropriately and everything went ok on its own.
I didn't have to enable anything fancy
I'm busy writing a driver for a UART. The, struct uart_port has a field uartclk see this link. According to a slide set I found from free-electrons, this is among the most important fields to initialize. Yet, the Xilinx AXI UART Lite, which I'm writing a driver for, doesn't initialize this member see this link to see.
I'm wondering about the importance of this field. What is this in relation to a UART? Why is it important? What role does it play in the serial core?
Thanks
P.S. I know there's a driver existing. However, this driver assumes the UART Lite is to be used in an embedded environment. In the application I'm writing to, this is not the case.
The UART like any other IP in the system has to have functional and interface clocks. In some IPs it might be same clock, in some it might be more interface or functional clocks. The uartclk field reflects the actual frequency on the input to baudrate generator (don't be confused by the frequency of functional clock which most of the time is constant). When user calls termios to set a desired baudrate the UART driver for actual hardware recalculates uartclk, if needed, and bottom layer, if used, configures the registers. That's how 8250 works. In other cases it might be left unused, if, for example, serial hw driver does everything on its own.
I'm trying to implement S-MAC protocol on waspmote xbee sensors and i know it has its own CSMA/CA. So first of all I need to understand the basic of xBee collision avoidance.
Two senders set up in api mode in libraries and both periodically sending single bytes to a common receiver. I reduce the delay and many changing in libabries to make collision and to see how algorithm works. But when i monitor data at the receiver all looks as expected at the receiver .. byte1, byte 2 .. byte1, byte2.
Do u have any idea how can i make collision?
Are you sniffing the 802.15.4 traffic? That's the only way you'd see a collision.
The XBee module buffers the data you want to send, using the host communication parameters (baud rate, API mode, etc.) and then sends it out over 802.15.4 at 250kbps. The module has all of the collision avoidance built in, and will retransmit as necessary to deliver your message. If it's unable to deliver after some number of transmission attempts, you'll get a Transmit Status frame indicating failure.
On the receiving end, it buffers the data and delivers it to the local host using local serial settings (baud rate and API mode).
If you're trying to implement S-MAC, you need a different radio processor where you have low-level control over the radio. The XBee module provides an application layer and handles the MAC layer itself.
I am trying to force a 9-bit protocol on a UART in embedded Linux. Currently I am testing this out on the am335x_evm board. I am planning on doing this using stick parity. Ideally I was hoping I would not need to actually modify any of the code for the omap-serial.c driver.
The reason for the 9-bit protocol is to support some legacy hardware that uses it. The parity bit needs to be 1 for the address portion of the message, 0 for the data portion, then 1 again for the termination byte.
I was planning on having a process running in user space that would interface with the UART through standard system calls (open, write, read, ioctl, tcsetattr, etc). I would configure the UART to enable parity and set the stick parity. I would then set the parity to even and call write() to send out my address data. I would then set the parity to 0 and send out the data. My concern is if I change the parity from 1 to 0, when does that take affect? If the UART is not done sending all the address data, will the change in parity apply to any unsent data?
Ended up writing my own 9-bit uart driver. Was the easiest and most efficient solution.
Proper way is to set cs9 on your serial port (and possibly no parity), provided that hardware and driver support this.
I'll search for a link for you...
I am using EVK1105 development board with AVR Studio 5 as development IDE for my AVR project.
I am using FreeRTOS in it. I have 3 USART ports on this board. One external module is connected to my AVR32 board via USART-RS232 mode. It sends me continuous serial data to my board on USART0 with 19230 baudrate, 7-databits, odd parity, stopbit-1 and normal-channel mode. I created a new task for this purpose. After each 9 data bytes it sends '\n' and '\r'. So in my task I keep on collecting the 9 databytes in a string buffer and then transmit it on USART1. I am using polling method to collect data from USAR0 which is receiving port. But I am facing problem in receiving data. I don't know if its timing issue or something or the scheduler switches the task while collects the data. But I don't get the required data.
Following are things I have already checked as troubleshooting
1. Connected my external module to my PC hyper-terminal which gives me perfect result.
2. Implemented the same thing of using receiving from USART0 and whatever received is transmitted to USART1 as without FreeRTOS. Its works fine.
Please suggest some idea what may be wrong. I am using a queue to communicate between Tx and Rx task to pass the string buffer from USART0 to USART1. Is it problem in handling queue? How can I troubleshoot the queue?
I am using a delay of 50ms in my infinite task loop in Rx Task. Can it create a problem? If I don't use any delay the OS crashes. Please suggest some good practices to create a new task in FreeRTOS so that I will not get any timing issue.
For such a use case, I would not use a polling method with 50ms delay to retrieve data from UART peripheral. You can easily lose received data depending on the system load and UART reception buffer size.
At least use an interrupt on UART data reception that copies every received byte into a local buffer that will be read by your TX thread.
You can have an even better solution using a DMA channel to receive your data frame and be notified when 9 bytes have been received. I don't know if your AVR device has a DMA peripheral or not.
Are you still working on this? The statement of your problem is vague, but there I have several suggestions/leading questions.
1) You may want some documents to see what the registers are
Get the giant datasheet pdfs at
http://www.atmel.com/dyn/products/product_docs.asp?category_id=163&family_id=607&subfamily_id=2138&part_id=4117
2) In this and an earlier post you state that you have, in some cases, been able to RX data. You will need to find the USART HW initialization code from those example projects and get them into the freeRTOS example project. In particular calls to
gpio_enable_module() with {AVR32_USART0_RXD_0_0_PIN, AVR32_USART0_RXD_0_0_FUNCTION}
To connect to USART to CPU
and i believe
InitRs232()
Just doing this requires poking around a lot of code - there's alot of dependencies.
2) What function are you calling to retrieve data from USART0? 19kbaud is approximately 2000bytes/sec or 1 byte/0.5ms, so 50ms polling is not nearly enough. I'd suggest that your RX task poll continuously (never sleep explicitly) but at a lower priority than the TX task.
3) Concentrate on debugging the RX task at the call to retrieve data. Use the debugger to look at the hardware registers for the usart. In particular
USART0 cr register AVR32_USART_CR_RXEN_MASK should be set to enable RX
USART0 csr register AVR32_USART_CSR_RXRDY_MASK will indicate if there is new data there
You can also check the overlow flag to see if you have missed some data.
When the read of USART0 rhr occurs it should be a byte that you sent.
If you are still working on this I can look into this a bit more.